简体   繁体   English

用于通知等待模式的C ++多线程算法设计

[英]C++ multi-threaded algorithm design for notify-wait pattern

I'm looking for an advice and code samples of a multi-threaded implementation on Windows of the following algo: 我正在寻找以下算法的Windows上的多线程实现的建议和代码示例:

  • Thread1: Take input1 , do work, notify Thread2 , continue work. Thread1:接受input1 ,做工作,通知Thread2 ,继续工作。
  • Thread2: Take input2 , do work, wait for notification from thread2, do some processing, notify Thread3 , continue work. Thread2:接受input2 ,做工作,等待来自thread2的通知,做一些处理,通知Thread3 ,继续工作。
  • Thread3: Take input3 , do work, wait for notification from thread3, do some processing, notify Thread4 , continue work. Thread3:接受input3 ,做工作,等待来自thread3的通知,做一些处理,通知Thread4 ,继续工作。 etc.. 等等..

Since I'm novice to C++, I'm not sure what mechanism to choose to send/receive notification between threads. 由于我是C ++的新手,我不确定选择在线程之间发送/接收通知的机制。
I considered several approaches: mutex , semaphore , critical section , but these seem for locking mostly, not for wait-notify. 我考虑了几种方法: mutexsemaphorecritical section ,但这些似乎主要是锁定,而不是等待通知。

Besides the usual helpers you already listed you should take a look at condition variable . 除了你已经列出的常用助手之外,你应该看一下条件变量

The condition_variable class is a synchronization primitive that can be used to block a thread, or multiple threads at the same time, until: - a notification is received from another thread [...] condition_variable类是一个同步原语,可用于同时阻塞线程或多个线程,直到: - 从另一个线程收到通知[...]

When a condition variable is used, thread 2 can wait until it was `notified' so thread 2 can continue and so on. 当使用条件变量时,线程2可以等到它被“通知”,因此线程2可以继续,依此类推。 Here is a simple example: 这是一个简单的例子:

std::mutex mtx;
std::condition_variable cv;
static bool ready = false;

static void set ()
{
  {
    std::unique_lock<std::mutex> lck(mtx);
    while (!ready)
      cv.wait(lck);
  }

  std::cout << "message received" << std::endl;
}

static void go()
{
  std::unique_lock<std::mutex> lck(mtx);
  ready = true;

  // here we set the condition variable for thread1
  cv.notify_all();
}

int main ()
{
  std::thread thread1 = std::thread(set);

  go();
  thread1.join();
  return 0;
}

Say each thread's task function looks something like this: 假设每个线程的任务函数看起来像这样:

void threadfunc()
{
    MSG winmsg;
    BOOL rval;

    while (GetMessage(&winmsg, (HWND__ *) -1, 0, 0) != -1)
    {
        DoThreadProcessing();
    }
    // GetMessage failed. Find out why and try to recover or die gracefully
}

This blocks on GetMessage until the thread is woken by the arrival of a message sent by this next function 这将阻止GetMessage,直到线程被此下一个函数发送的消息到达而被唤醒

bool PostMsg(DWORD & ThreadId)
{
    if (PostThreadMessage(ThreadId,
                          WM_USER,
                          (WPARAM) NULL,
                          0); != 0)
    {
        return true;
    }
    else
    {
        // failed. Find out why and try to recover or die gracefully
        return false;
    }
}

through the magic of PostThreadMessage . 通过PostThreadMessage的魔力。

If you care what sort of message is sent, you can send simple information like a number in the Msg parameter and pull it from winmsg.message . 如果您关心发送什么类型的消息,您可以发送简单信息,如Msg参数中的数字,并从winmsg.message Keep the number small because Windows uses the upper half of message for it's own nefarious purposes. 保持数字较小,因为Windows使用message的上半部分是出于自己的恶意目的。

If you need more complex messaging, Mutex not correctly used? 如果您需要更复杂的消息传递, Mutex未正确使用? Continuation of past questions covers this. 继续过去的问题涵盖了这一点。

So in the OP's case, thread 1 calls PostMsg with thread 2's handle to wake thread 2. Thread 2 calls PostMsg with thread 3's handle and so on. 所以在OP的情况下,线程1调用带有线程2的句柄的PostMsg来唤醒线程2.线程2用线程3的句柄调用PostMsg,依此类推。

You may even be able to use std::thread 's native_handle method to stay mostly within the standard library, but I've never tested this. 您甚至可以使用std :: threadnative_handle方法主要保留在标准库中,但我从未测试过这个。 Let me know if it works. 如果有效,请告诉我。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM