Reputation: 469
I'm looking for an advice and code samples of a multi-threaded implementation on Windows of the following algo:
input1
, do work, notify Thread2
, continue work.input2
, do work, wait for notification from thread2, do some processing, notify Thread3
, continue work.input3
, do work, wait for notification from thread3, do some processing, notify Thread4
, continue work.
etc..Since I'm novice to C++, I'm not sure what mechanism to choose to send/receive notification between threads.
I considered several approaches: mutex
, semaphore
, critical section
, but these seem for locking mostly, not for wait-notify.
Upvotes: 1
Views: 1141
Reputation: 33982
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
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.
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
. Keep the number small because Windows uses the upper half of message
for it's own nefarious purposes.
If you need more complex messaging, Mutex not correctly used? 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.
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. Let me know if it works.
Upvotes: 0
Reputation: 1863
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 [...]
When a condition variable is used, thread 2 can wait until it was `notified' so thread 2 can continue and so on. 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;
}
Upvotes: 3