C++原子变量的使用案例

news2024/12/21 18:56:07

说明

核心原子变量是pDeviceStatus,该变量的夸线程修改,就不需要使用锁了;

std::atomic<IPDeviceStatus*> pDeviceStatus = new IPDeviceStatus();

代码功能

某公共场所使用的IP喇叭,类似物联网设备,基于嵌入式的设备的应用,应用层通过http协议推送语音文件进行播放,这是客户的项目,不变全部公开

核心代码

// IPSound.cpp: 定义应用程序的入口点。
//
#include <iostream>
#include "IPSound.h"
#include "IPSoundDeviceModel.h"
#include "httplib.h"
#include "json.hpp"
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <vector>
#include <sys/time.h>

#define MAX_FILE_LEN 1024


#define MP3_PLAY_PRG "mpg123"
#define WAV_PLAY_PRG "aplay"

#define MP3_AUDIO "mp3"
#define WAV_AUDIO "wav"

using json = nlohmann::json;

// std::atomic<IPDeviceStatus*> pDeviceStatus = new IPDeviceStatus();
std::atomic<IPDeviceStatus*> pDeviceStatus = new IPDeviceStatus();
std::atomic<IPSoundDeviceModel*> pDevModel = 0;

bool gForceExit = false;


void* stopPlay(void *param)
{
    std::cout << "receive force stop command --- Start" << endl;
    
    ...

    std::cout << "receive force stop command --- End" << endl;

    return 0;
}

void* playAudio(void *param)
{
    char command[MAX_FILE_LEN *2 ] = {0};

    string subfix = (*pDeviceStatus).getCurrentFileSubfix();
    ...
    // 如果没有需要播放的文件
    (*pDeviceStatus).mStatus = 0;
    // 重置当前文件信息
    (*pDeviceStatus).reset();

    return 0;
}


void handle_post(const httplib::Request& req, httplib::Response& res) 
{
    // 处理POST请求的逻辑
    std::cout << "Received a POST request!" << std::endl;
    
                std::string postData = req.body; 
            std::cout << postData << endl;

            auto size = req.files.size();
            std::cout << "--0-->" << size << endl;
            auto ret = req.has_file("file");

            int playStatus = 0;
            // 如果是停止播放
            if (!ret){
                std::cout << "hell01" << endl;
                // 启动一个线程执行任务
                pthread_t t;
                pthread_create(&t,nullptr,stopPlay,nullptr);

                std::cout << "hell02" << endl;
                // stopPlay();

                // stop Play
                // 设置播放状态
                (*pDeviceStatus).mStatus = 0;
                std::cout << "hell03" << endl;

            }

            else{
                const auto& file = req.get_file_value("file");
                std::cout << "--1-->" << file.filename << endl;
                std::cout << "--2-->" << file.content_type<< endl;

                // // 将上传的图像文件写入本地文件系统中
                char filePath[MAX_FILE_LEN] = {0};
                
                struct timeval tv;
                
                if (gettimeofday(&tv, NULL) == -1) {
                    perror("Failed to get current time");
                    exit(EXIT_FAILURE);
                }
                
                unsigned long milliseconds = tv.tv_sec * 1000 + tv.tv_usec / 1000;
                

                sprintf(filePath, "./tmp/%lu_%s",milliseconds, file.filename.c_str());
                //strcpy(filePath,"/home/user/aaa.mp3");
                cout << "save file path = " << filePath << endl;
                FILE* fp = fopen(filePath, "wb");
                if (!fp) {

                    cout << "file cache failed" << endl;
                    res.status = 500;
                    return;
                }
                fwrite(file.content.data(), sizeof(char), file.content.size(), fp);
                fclose(fp);

                // 如果当前正在播放,则进入队列
                if ((*pDeviceStatus).mStatus == 1){
                    std::cout << "==============设备忙,添加到等待队列==============" << endl;
                    AudioTask audioTaks ;
                    audioTaks.mTaskID = "aaa0001";
                    audioTaks.mAudioFile = filePath;
                    
                    (*pDeviceStatus).mPlayList.push_back(audioTaks);
                    playStatus = 2;
                }
                else{
                    (*pDeviceStatus).mCurrentFile.mTaskID = "aaa0001";
                    (*pDeviceStatus).mCurrentFile.mAudioFile = filePath;
                    

                    playStatus = 1;
                    // 设置播放状态
                    (*pDeviceStatus).mStatus = 1;
                    // 调用播放函数

                    // 启动一个线程执行任务
                    pthread_t t;
                    pthread_create(&t,nullptr,playAudio,nullptr);

                    //playAudio();
                }
            }


    json rtnJson;
    rtnJson["code"] = "00000000";

    if (playStatus == 1){
        rtnJson["msg"] =  "添加成功立即播放";
    }
    else if (playStatus == 0){
        rtnJson["msg"] =  "取消播放成功";
    }
    else{
        rtnJson["msg"] =  "设备忙,已排队";
    }

    // 返回响应内容
    res.set_content(rtnJson.dump(), "application/json;charset=utf-8");
}

int main(void)
{
    using namespace httplib;

    pDevModel = new IPSoundDeviceModel();

    Server svr;

    // curl http://192.168.7.103:8888/api/v1/player/deviceInfo
    // 查询设备信息
    svr.Get("/api/v1/player/deviceInfo", [&](const Request& req, Response& res) {
            std::cout << "/api/v1/player/deviceInfo " << endl;
            res.set_content((*pDevModel).toJsonString(), "application/json;charset=utf-8");
        });

    // curl http://192.168.7.103:8888/api/v1/player/status
    // 查询设备状态
    svr.Get("/api/v1/player/status", [&](const Request& req, Response& res) {
            std::cout << "/api/v1/player/status" << endl;
            res.set_content((*pDeviceStatus).toJsonString(), "application/json;charset=utf-8");
        });

    // curl -X POST "audioId=&1&volume=30" -F "file=@/home/user/Work/9.mp3" http://192.168.7.103:8888/api/v1/player/audio
    // 播放音乐
    svr.Post("/api/v1/player/audio", [&](const auto& req, auto& res) {
            std::cout << "multipart invoke " << endl;
            handle_post(req,res);
            std::cout << "multipart invoke END----------------" << endl;
    });

    // 升级
    // curl -X POST "audioId=&1&volume=30" http://192.168.7.103:8888/api/v1/player/audio
    svr.Post("/api/v1/player/upGrade", [&](const Request& req, Response& res) {
            std::cout << "/api/v1/player/upGrade" << endl;
            res.set_content((*pDeviceStatus).toJsonString(), "application/json;charset=utf-8");
        });

    std::cout <<  "Server on :" << DEFAULT_PORT << endl;

    svr.listen("0.0.0.0", DEFAULT_PORT);
}

我公司承接各类技术服务,主要聚焦于:stm32、单片机、嵌入式、QT应用开发、Web+Python+Django应用开发。欢迎合作。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1487534.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Vue3自定义文章列表组件

一、Vue3的代码展示 <template><div><div v-for"article in articles" :key"article.id" class"article-card"><div class"author-info"><img :src"article.avatar" alt"Author Avatar&qu…

水电站数字孪生:水力发电在可视化领域的应用

自水轮机的早期发明被用于农业灌溉&#xff0c;到 18 世纪末期的工业革命促使水轮机技术的改良&#xff0c;再到 19 世纪末水利发电的崛起&#xff0c;直至今日&#xff0c;智慧水电站数字孪生技术正处于蓬勃发展之中。通过整合物联网、大数据、云计算等现代信息技术&#xff0…

PYCHARM PYSIDE6 QT 打包异常3种处理方式 no qt platform plugin could be initialized

安装有PYSIDE6的电脑 异常错误 … no qt platform plugin could be initialized … 变量名&#xff1a;QT_QPA_PLATFORM_PLUGIN_PATH &#xff08;一个字都不能改&#xff01;&#xff01;&#xff09; 自己环境变量值&#xff1a;D:\Users\topma\anaconda3\Lib\site-package…

【STM32】STM32学习笔记-FLASH闪存(48)

00. 目录 文章目录 00. 目录01. FLASH简介02. 闪存模块组织03. FLASH基本结构04. FLASH解锁05. 使用指针访问存储器06. 程序存储器编程07. 选项字节08. 选项字节编程09. 选项字节擦除10. 器件电子签名11. 附录 01. FLASH简介 STM32F1系列的FLASH包含程序存储器、系统存储器和选…

HarmonyOS Stage模型 用程序运行切换 验证UIAbility 启动模式(下) 验证:specified启动模式 Ability间切换

上文 HarmonyOS Stage模型 用程序运行切换 验证UIAbility 启动模式(上) 验证:singleton、multiton、standard启动模式 我们已经验证完了 singleton multiton standard 三种启动模式 留下了毕竟复杂的 specified 这里 首先 我们要写两个不同的界面 index 编写代码如下 import…

就业班 2401--2.29 Linux Day8--存储管理2(LVM)+swap+磁盘阵列raid

&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;小伙伴们一定要看到最后&#xff0c;有彩蛋呢^--^ 一、存储管理Ⅱ 逻辑卷LVM &#xff08;Logical Volume Manager&#xff08;逻辑卷管理&#xff09;的简写&#xff09; LVM管理 lvm概念&#xf…

即时设计案例分享: 网页设计案例解析

优秀的网页设计案例可以帮助设计快速完成设计项目&#xff0c;优秀的网页设计网站也是设计师的灵感电站。网页承载着品牌希望向访问者传递的信息。当用户进入网站时&#xff0c;人们对网站的第一印象开始潜移默化地形成。因此&#xff0c;优秀的网页设计非常重要&#xff0c;这…

uniapp问卷调查(单选)

前言 该代码片段只支持问卷调查的单选功能 使用组件库 配置 | uView 2.0 - 全面兼容 nvue 的 uni-app 生态框架 - uni-app UI 框架 (uviewui.com) 代码 <template> <view> <view v-for"(item, index) in radiolist1" :key"index"> …

LeetCode --- 无重复字符的最长子串

题目描述 无重复字符的最长子串 找到无重复的最长连续字符串。 示例1中 abc | bca | cab 都符合题意。输出3即可。 代码 可以使用暴力枚举 哈希表&#xff0c;哈希表来判断是否重复&#xff0c;枚举来判断每一种情况&#xff0c;需要开两层for循环&#xff0c;时间复杂度n…

Linux --- 应用层 | HTTP | HTTPS

前言 前面写的TCP/UDP客户端在访问服务端的时候&#xff0c;需要输入ip地址和端口号才可以访问&#xff0c; 但在现实中&#xff0c;我们访问一个网站是直接输入的一个域名&#xff0c;而不是使用的ip地址端口号。 比如在访问百度 https://www.baidu.com/的时候&#xff0c; …

操作系统|概述|系统分类——笔记

1.1_1操作系统的概念和功能 操作系统的概念 操作系统&#xff08;Operating System&#xff0c; OS&#xff09; 是指控制和管理整个计算机系统的 硬件和软件 资源&#xff0c;并合理地组织调度计算机和工作和资源的分配&#xff1b; 1操作系统是系统资源的管理者 以提供给用…

Springboot 过滤器、拦截器、全局异常处理

Springboot 过滤器、拦截器、全局异常处理 一 过滤器&#xff08;Filter&#xff09; 过滤器是JavaWeb三大组件&#xff08;Servlet&#xff0c;Filter&#xff0c;Listener&#xff09;之一。 Filter可以把对资源的请求拦截下来&#xff0c;从而实现一些功能。 注意&#…

罐头食品加工污废水需要哪些工艺设备

罐头食品加工是目前广泛应用于食品行业的一种加工方式&#xff0c;由于其加工过程中产生的废水所含有的有机物质和化学物质含量较高&#xff0c;对环境造成了一定的污染问题。为了解决这一问题&#xff0c;罐头食品加工污废水需要采用一系列的工艺设备进行处理和净化。 首先&am…

技术实践|百度安全「大模型内容安全」高级攻击风险评测

1、引子 2023年10月16日&#xff0c;OWASP发布了《OWASP Top 10 for LLM Applications》&#xff0c;这对于新兴的大语言模型安全领域&#xff0c;可谓一份纲领性的重要报告。 OWASP是开放式Web应用程序安全项目&#xff08;Open Web Application Security Project&#xff0…

Mysql运维篇(七) 部署MHA--完结

一路走来&#xff0c;所有遇到的人&#xff0c;帮助过我的、伤害过我的都是朋友&#xff0c;没有一个是敌人。如有侵权&#xff0c;请留言&#xff0c;我及时删除&#xff01; 一、MHA软件构成 Manager工具包主要包括以下几个工具&#xff1a; masterha_manger 启…

【直播来袭】威睿电池:车载ECU网络安全开发落地开发实践|谈思AutoSec直播课第42期

如果恶意黑客导致动力总成和底盘ECU出现问题&#xff0c;你会感到害怕甚至不敢想。车辆电气系统中的所有ECU都可能成为目标。更不用说互联车辆了。为了防止软件被未经授权的操作或访问至关重要的关键材料&#xff0c;现代车辆需要强大的IT安全机制来与外界隔离。 由于汽车智能…

.md转pdf

1、使用vscode安装Markdown PDF Markdown PDF 打开预览转pdf,同目录下自动生成pdf文件

中科大计网学习记录笔记(十七):拥塞控制原理 | TCP 拥塞控制

前言&#xff1a; 学习视频&#xff1a;中科大郑烇、杨坚全套《计算机网络&#xff08;自顶向下方法 第7版&#xff0c;James F.Kurose&#xff0c;Keith W.Ross&#xff09;》课程 该视频是B站非常著名的计网学习视频&#xff0c;但相信很多朋友和我一样在听完前面的部分发现信…

VulnHub打靶记录——Socnet

靶机下载地址&#xff1a;https://www.vulnhub.com/entry/boredhackerblog-social-network,454/ 将靶机设置为NAT模式并启动。 主机发现&信息收集 靶机和 kali 在同一网段&#xff0c;使用nmap扫描网段主机&#xff0c; nmap 192.168.50.1/24其中192.168.50.130是本机&…

UV画贴图时如何去掉一部分

1.纹理先选psd 2. altshift 把要去掉的中选中 选择几何体-隐藏选择