安全线程队列 — C++

一、废话少说,上代码,安全队列

#pragma once
#include <queue>
#include <memory>
#include <mutex>
#include <condition_variable>

template <typename T>
class SafeQueue
{
private:
    mutable std::mutex mMutex;
    std::queue<T> mQueue;
    std::condition_variable mCond;

public:
    SafeQueue() {}
    SafeQueue(SafeQueue const &other)
    {
        std::lock_guard<std::mutex> lk(other.mMutex);
        mQueue = other.mQueue;
    }

    void push(T new_value)
    {
        std::lock_guard<std::mutex> lk(mMutex);
        mQueue.push(new_value);
        mCond.notify_one();
    }

    void waitAndPop(T &value)
    {
        std::unique_lock<std::mutex> lk(mMutex);
        mCond.wait(lk, [this]() { return !mQueue.empty(); });
        value = mQueue.front();
        mQueue.pop();
    }

    std::shared_ptr<T> waitAndPop()
    {
        std::unique_lock<std::mutex> lk(mMutex);
        mCond.wait(lk, [this]()  { return !mQueue.empty(); });
        std::shared_ptr<T> res(std::make_shared<T>(mQueue.front()));
        mQueue.pop();
        return res;
    }

    bool tryPop(T &value)
    {
        std::lock_guard<std::mutex> lk(mMutex);
        if (mQueue.empty())
            return false;
        value = mQueue.front();
        mQueue.pop();
        return true;
    }

    std::shared_ptr<T> tryPop()
    {
        std::lock_guard<std::mutex> lk(mMutex);
        if (mQueue.empty())
            return std::shared_ptr<T>();
        std::shared_ptr<T> res(std::make_shared<T>(mQueue.front()));
        mQueue.pop();
        return res;
    }

    bool empty() const
    {
        std::lock_guard<std::mutex> lk(mMutex);
        return mQueue.empty();
    }
};

二、安全队列一般使用在多线程调用,容易出现调用错乱,为了能同步调用,把每一个回调都根据先后顺序放在一个安全队列中执行

三、举例使用安全队列
在一个类中有多个回调通知。

enum class ManagerEventType
{
    NOTIFY_Base_1_RESULT,
    NOTIFY_Base_2_Begin,
    NOTIFY_Base_3_END,
};

struct Slot
{
    std::string area;
    std::string key;
    std::string value;
};

struct ManagerEvent
{
    ManagerEventType eventType;
    Slot slot;
    bool status;
};

class Manager : public RESULTCallback, 
                public BeginCallback, 
                public ENDCallback
{
public// 初始化mInitThreadExit标志位线程队列是否退出
Manager::Manager()
    : mInitThreadExit(false),
      mEventQueue(),
      mWorkThread(nullptr) {

}

// 初始化的时候执行这个同步线程。
void AISpeechManager::init()
{
    VLOGD("AISpeechManager::init() -> start");
    mWorkThread = std::make_shared<std::thread>(&AISpeechManager::workLoop, this);
}
 
AISpeechManager::~AISpeechManager()
{
    if (mInitThreadExit == false) {
        mInitThreadExit = true;
          // 等待线程执行结束之后再退出,joinable检测是否用过join,没有用过在使用join
        if ((mWorkThread != nullptr) && (mWorkThread->joinable())) {
            mWorkThread->join();
        }
    }
}

private:
   Slot mslot;
   std::atomic<bool> mInitThreadExit{false};
   SafeQueue<ManagerEvent> mEventQueue;
   std::shared_ptr<std::thread> mWorkThread;

private:

   // 异步通知过来先统一扔进安全队列中等待上一个执行结束之后会通知先一个调用执行
   void resulte() {
         mslot.area = "学号"
          mslot.key = "123"
          mslot.value = "liming"
          ManagerEvent event;
          event.eventType = ManagerEventType::NOTIFY_Base_1_RESULT;
          event.slot= mslot;
          sendEvent(event);
    }
    
    void beginSts(bool beginSts){
          ManagerEvent event;
          event.eventType = ManagerEventType::NOTIFY_Base_2_Begin;
          event.status = begin;
          sendEvent(event);
    }
    void end(){
          ManagerEvent event;
          event.eventType = ManagerEventType::NOTIFY_Base_3_end;
          event.status = begin;
          sendEvent(event);
   }
   
    void sendEvent(ManagerEvent event) {
       mEventQueue.push(event);
    }
    
    void workLoop() {
       while (!mInitThreadExit) {
        ManagerEvent event;
        VLOGD("Manager Begin wait for event");
        mEventQueue.waitAndPop(event);
        VLOGD("Manager Receive event:%d", event.eventType);
        switch (event.eventType) {
            // 在下面case中执行扔进线程队列中的方法要做的事情
            case ManagerEventType::NOTIFY_Base_2_Begin: { 
                if (event.status) {
                    // status is ture do something
                } else {
                    // status is false do something
                }
            }
            case ManagerEventType::NOTIFY_Base_1_RESULT: { 
                 Slot slot = event.slot;
                 // do something
            }
            case ManagerEventType::NOTIFY_Base_3_end:{ 
                 // do something
            }
    }
}
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值