C++ 跨线程处理同步/异步消息

  为了不阻塞主线程,将主线程发过来的命令处理为不同的事件,放到另一个线程去执行,包括同步和异步处理。

  注:同一个进程,多线程。

 

  为了保证线程间的共享资源保护以及线程间的消息机制,用到了下面几个系统库资源:

    std::mutex

    std::unique_lock

    std::conditional_variable

 

  1、消息 结构体 和 事件

    enum Op
    {
        EVENT_A = 0,
        EVENT_B,
        EVENT_C,
    };
   
    //最重要的是operation和isSyncCmd, 其它的都是传参,选填。
    struct Command
    {
        Op          operation;
        int32_t     arg;
        long     larg;
        const void*       parg;
        bool        barg;
        std::string str;
        bool        isSyncCmd; //是否是同步事件
    };

  2、添加消息

void postCommand(const Command& cmd)
{
    std::unique_lock lock(mLock);
    mCommandQueue.push(cmd);

    mWakeSignal.notify_all(); //唤醒处理事件的线程
    if (cmd.isSyncCmd) { //如果是同步消息,则等待消息处理完成
        mSyncMsgSignal.wait(lock);
    }
}

3、处理消息

void msgProcessLoop()
{
    bool run = true;
    while (run){
        {
            std::unique_lock lock(mLock);
            while(!mCommandQueue.empty()) { //处理掉所有的事件
                const Command cmd = mCommandQueue.front();
                mCommandQueue.pop();
                lock.unlock();//不阻塞主线程,主线程依然可以拿到锁,往mCommandQueue中添加event。
                processEvent(cmd);
                lock.lock();
            }
            mWakeSignal.wait(lock);//消息处理完成之后,释放锁,并进入睡眠状态
        }
    }
}

void processEvent(const Command& cmd)
{
    switch (cmd.operation)
    {
        case EVENT_A:
            //do A
            break;
        case EVENT_B:
            //do B
            break;
        case EVENT_C:
            //do C
            break;
    }

    if (cmd.isSyncCmd) {
        mSyncMsgSignal.notify_all();
    }
}

4、使用

   主线程通过调用postCommand往事件队列里面添加新的事件。eg:

  void doTaskA()

  {
      struct Command cmd = {
          .operation = Op::EVENT_A,
          .isSyncCmd = false,
      };
      postCommand(cmd);
  }

  然后,另外起一个thread,执行msgProcessLoop().

 

  如果是同步事件,就 将 isSyncCmd置为true 即可, 这种情况下postCommand就不会立即返回,而是等待事件处理完成之后才会返回。

你可能感兴趣的:(c++,linux)