Deep Learner
Deep Learner

Reputation: 469

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:

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

Answers (2)

user4581301
user4581301

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

HelloWorld
HelloWorld

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

Related Questions