Ordered notification of threads waiting on a condition (C++, boost) - c++

Does anyone know of a condition variable class that allows notification of threads waiting for a condition to be notified in the order in which they started waiting?
I'm currently using the boost class condition_variable, but calling condition_variable::notify_one() wakes up a random thread, not the thread that first called condition_variable::wait(). I also tried adding thread ids to a queue before calling condition_variable::wait(), so that I can call condition_variable::notify_all() upon which all waiting threads wake up, check the queue and either wait again or proceed (only one thread, namely the thread first in queue). The problem is that calling notify_all() twice does not guarantee that all threads are waking up twice, thereby losing notifications. Any suggestions?

It is strange that you require threads to be woken in particular order and sounds suspicious about your design. Anyway idea is that you can have queue of condition variables (one per thread) and you would call notify_one() for one from top of the queue. In waiting thread you need to do additional logic to check that it was not sporadically interrupted from wait. Again sounds strange why you need thread to wake up in particular order and you may want to rethink your design.

Related

If we use notify_one() to wake a thread, do we still need yield() - in C++?

yield(): https://en.cppreference.com/w/cpp/thread/yield
notify_one(): http://www.cplusplus.com/reference/condition_variable/condition_variable/notify_one/
Case:
Thread A is supposed to finish whatever it is doing and then wake thread B to do its job.
I wrote a notify_one() call in the thread A' run() function.
Is a case possible that thread A signals notify_one() but still thread A is scheduled again even though thread B is ready?
Are notify_one() and yield() equivalent of each other?
yield and notify_one are unrelated.
yield is a process request (to the OS) to give up its current time slice. The thread will still be scheduled next time around. Imagine that a process is allocated 10ms. If it calls yield after 5ms, the OS can run another process. It still gets the full 10ms next time it's its turn to run. The OS does not have to fulfill the request.
condition_variable::notify_one is used in conjunction with condition_variable::wait. If there are any threads waiting, notify_one is guaranteed to wake one of them. If there are no threads waiting, notify_one will do nothing.
Note that a condition variable, when calling wait, must be used with 1 mutex that protects some shared state (the condition), and it is waiting for another thread to signal when the condition is true.
Is a case possible that thread A signals notify_one() but still thread A is scheduled again even though thread B is ready?
Yes. With Mesa semantics, signaling a waiting thread merely unblocks the other thread. The current thread may continue running until it runs out of time. With Hoare semantics, the signaling thread will immediately switch to the waiting thread. However, pretty much all implementations of conditions use Mesa semantics.
Are notify_one() and yield() equivalent of each other?
"Equivalent" would mean that they do the same thing. That is not the case. I think you mean to ask if they are complimentary, or if they are part of the same synchronization scheme, and the answer is no, as I explained above.
If we use notify_one() to wake a thread, do we still need yield()
If Thread A just woke Thread C with nofity_one and you wish to run Thread C as soon as possible, you can call yield to give up the rest of Thread A's time slice. However, the OS is not required to grant your request. And there may be many threads scheduled before Thread C that you have no control over.
There is a difference between both. There is a possibility that in your case you can use either of them with same effect. yield is more generic and notify_one provides more control on the flow of program.
yield: Relinquish processor so that OS can possibly schedule any other thread.
notify_one: Signal a condition so that one of the thread waiting on this condition can resume.
Thread A is supposed to finish whatever it is doing and then wake
thread B to do its job.
notify_one is the right choice here where one thread waits on the condition while the other thread can signal it.

What's the purpose of SignalObjectAndWait regards there is SetEvent and WaitForSingleObject?

I just realized there is SignalObjectAndWait API function for Windows platform. But there is already SetEvent and WaitForSingleObject. You can use them together to achieve the same goal as SignalObjectAndWait.
Based on the MSDN, SignalObjectAndWait is more efficient than separate calls to SetEvent and WaitForSingleObject. It also states:
A thread can use the SignalObjectAndWait function to ensure that a worker thread is in a wait state before signaling an object.
I don't fully understand this sentence, but it seems that efficiency is not the only reason why we need SignalObjectAndWait. Can anybody provide a scenario where SetEvent + WaitForSingleObject fails to provide the functionality that SignalObjectAndWait offers?
My understanding is that this single function is more efficient in the way that it avoid the following scenario.
The SignalObjectAndWait function provides a more efficient way to signal one object and then wait on another compared to separate function calls such as SetEvent followed by WaitForSingleObject.
When you you SetEvent and another [esp. higher priority] thread is waiting on this event, it might so happen that thread scheduler takes control away from the signaling thread. When the thread receives control back, the only thing that it does is the following WaitForSingleObject call, thus wasting context switch for such a tiny thing.
Using SignalObjectAndWait you hint the kernel by saying "hey, I will be waiting for another event anyway, so if it makes any difference for you don't excessively bounce with context switches back and forth".
The purpose, as MSDN explains is to ensure that the thread is in a Wait State BEFORE the event is signalled. If you call WaitForSingleObject, the thread is in a waitstate, but you can't call that BEFORE calling SetEvent, since that will cause SetEvent to happen only AFTER the wait has finished - which is pointless if nothing else is calling SetEvent.
As you know, Microsoft gives the following example of why we may ever need SignalObjectAndWait if we already need separate SetEvent and WaitForSingleObject (quote the Microsoft example):
A thread can use the SignalObjectAndWait function to ensure that a worker thread is in a wait state before signaling an object. For example, a thread and a worker thread may use handles to event objects to synchronize their work. The thread executes code such as the following:
dwRet = WaitForSingleObject(hEventWorkerDone, INFINITE);
if( WAIT_OBJECT_0 == dwRet)
SetEvent(hEventMoreWorkToDo);
The worker thread executes code such as the following:
dwRet = SignalObjectAndWait(hEventWorkerDone,
hEventMoreWorkToDo,
INFINITE,
FALSE);
This algorithm flow is flawed and should never be used. We do not need such a perplexing mechanism where the threads notify each other until we are in a “Race condition”. Microsoft itself in this example creates the Race Condition. The worker thread should just wait for an event and take tasks from a list, while the thread that generates tasks should just add tasks to this list and signal the event. So, we just need one event, not two as in the above Microsoft example. The list has to be protected by a critical section. The thread that generates tasks should not wait for the worker thread to complete the tasks. If there are tasks that require to notify somebody on their completion, the tasks should send the notifications by themselves. In other words, it is the task who will notify the thread on completion -- it is not the thread who will specifically wait for the jobs thread until it finishes processing all the tasks.
Such a flawed design, as in the Microsoft Example, creates imperative for such monsters like atomic SignalObjectAndWait and atomic PulseEvent -- function that ultimately lead to doom.
Here is an algorithm how can you achieve you goal set in your question. The goal is achieved with just plain and simple events, and simple function SetEvent and WaitForSingleObject - no other functions needed.
Create one common auto-reset event for all job threads to signal that there is a task (tasks) available; and also create per-thread auto-reset events, one event for each job thread.
Multiple job treads, once finished running all the jobs, all wait for this common auto-reset “task available” event using WaitForMultipleObjects - it waits two event - the common event and the own thread event.
The scheduler thread puts new (pending) jobs to the list.
The jobs list access has to be protected by EnterCriticalSection/LeaveCriticalSection, so no one ever accesses this list the other way.
Each of the job threads, after completing one job, before starting to wait for the auto-reset “task available” event and its own event, checks the pending jobs list. If the list is not empty, get one job from the list (remove it from the list) and execute it.
There have to be another list protected by critical section – waiting jobs thread list.
Before each jobs tread starts waiting, i.e. before it calls WaitForMultipleObjects, it adds itself to the “waiting” list. On exit from wait, it removes itself from this waiting list.
When the scheduler thread puts new (pending) jobs to the jobs list, it first enters critical section of the jobs list and then of the treads list - so two critical sections are entered simultaneously. The jobs threads, however, may never enter both critical sections simultaneously.
If there is just one job pending, the scheduler sets the common auto-reset event to the signaled state (call SetEvent) -- it doesn’t matter which of the sleeping job threads will pick up the job.
If there are two or more jobs pending, it would not signal the common event, but will count how many threads are waiting. If there are at least as many threads waiting as there are the jobs, signal the own event of that number of threads as there are events, and leave the remaining thread to continue their sleeping.
If there are more jobs than waiting threads, signal the own event for each of the waiting thread.
After the scheduler thread has signaled all the events, it leaves the critical sections - first of the thread list, and then of the jobs list.
After the scheduler thread has signaled all the events needed for the particular case, it goes to sleep itself, i.e. calls WaitForSingleObject with its own sleep event (that is also an auto-reset event that should be signaled whenever a new job appears).
Since the jobs threads will not start to sleep until the whole jobs list is depleted, you will no longer need the scheduler thread again. The scheduler thread will only be needed later, when a new jobs appears, not when a job is finished by the jobs thread.
Important: this scheme is based purely on auto-reset events. You won’t ever need to call ResetEvent. All the functions that are needed are: SetEvent and WaitForMultipleObjects (or WaitForSingleObject). No atomic event operation is needed.
Please note: when I wrote that a thread sleeps, it doesn't call "Sleep" API call - it will never be needed, it just is in the "wait" state as a result of calling WaitForMultipleObjects (or WaitForSingleObject).
As you know, auto-reset event, and the SetEvent and WaitForMultipleObjects function are very reliable. They exist since NT 3.1. You may always architect such a program logic that will solely rely on these simple functions -- so you would not ever need complex and unreliable functions that presume atomic operations, like PulseEvent or SignalObjectAndWait. By the way, SignalObjectAndWait did only appear in Windows NT 4.0, while SetEvent and WaitForMultipleObjects did exist from the initial version of Win32 – NT 3.1.

Continue executing another thread

I'm currently playing with WinAPI and I have proceeded to threads. My program has n threads which work with each other. There is one main thread, which writes some data to specific memory location and waits until thread working with specific memory location processes the data. Then whole procedure repeats again, without terminating any thread.
My problem is that busy waiting for second thread wastes too much time.
Is there any way to suspend current thread (to leave time for enother threads) or to solve this problem differently?
Please help.
I'm guessing that you're currently polling / busy waiting in your main thread, constantly checking the state of some completion flag the worker thread will set. As you note, this isn't desirable as you use some proportion of cpu bandwidth just waiting for the worker to complete. In some cases, this will reduce the amount of time your worker is scheduled for, delaying its completion.
Rather that doing this, you can use a synchronisation object such as Event or Semaphore to have your main thread sleep until the worker signals its completion.
You can use synchronization objects like mutex, semaaphores events etc for synchronization and WaitForSingleObject/WaitForMultipleObject API for thread waiting.

How does pthread_cond_broadcast works?

Say the broadcasting thread broadcasts while only 3 threads are waiting and the 4th thread call pthread_cond_wait after the broadcasting thread is done with broadcast, will the 4th thread ever get out of the waiting condition. And how is the condition variable reset, so that the broadcasting thread can rebroadcast sometimes later to the waiting threads.
will the 4th thread ever get out of the waiting condition
No, not until there's another broadcast or signal.
And how is the condition variable reset, so that the broadcasting
thread can rebroadcast sometimes later to the waiting threads.
It's simplest to imagine that everything that a condition variable does, is synchronized under the mutex associated with the condition variable. So at the time you broadcast, everything waiting is (somehow) put into a state where it is trying to wake up and take the mutex. Then, the broadcasting thread releases the mutex. So it's not really the condition variable that's "reset" when you broadcast, it's the first three threads that are moved from waiting on the condition variable, to waiting on the mutex.
In order to wait on the condvar, your 4th thread must first acquire the mutex. This might happen before or after the first three threads manage to wake up and take the mutex, but it clearly happens after the broadcast, and so your 4th thread is not in "trying to wake up" state, it's in "waiting for a signal or broadcast" state.
Actually it's more complicated than that -- you don't actually have to hold the mutex in order to broadcast a condition variable. So condition variables must include some additional internal synchronization (I don't know the specific details on linux), to make sure that all threads waiting before the broadcast get their state changed as a single operation.
Normally you might as well hold the mutex to broadcast, though, because you broadcast when you've just changed something that waiters want to see, and whatever that thing is that's looked at from lots of threads, is synchronized using the mutex. And there are a couple of awkward situations that you can avoid by always doing it that way.
will the 4th thread ever get out of the waiting condition.
No, not unless the condition variable is signalled while thread 4 is waiting.
The man page explains:
The pthread_cond_broadcast() call unblocks all threads currently blocked on the specified condition variable cond.
The pthread_cond_signal() and pthread_cond_broadcast() functions have no effect if there are no threads currently blocked on cond.

sleeping a thread in the middle of execution

What happens when a thread is put to sleep by other thread, possible by main thread, in the middle of its execution?
assuming I've a function Producer. What if Consumer sleep()s the Producer in the middle of production of one unit ?
Suppose the unit is half produced. and then its put on sleep(). The integrity of system may be in a problem
The thread that sleep is invoked on is put in the idle queue by the thread scheduler and is context switched out of the CPU it is running on, so other threads can take it's place.
All context (registers, stack pointer, base pointer, etc) are saved on the thread stack, so when it's run next time, it can continue from where it left off.
The OS is constantly doing context switches between threads in order to make your system seem like it's doing multiple things. The OS thread scheduler algorithm takes care of that.
Thread scheduling and threading is a big subject, if you want to really understand it, I suggest you start reading up on it. :)
EDIT: Using sleep for thread synchronization purposes not advised, you should use proper synchronization mechanisms to tell the thread to wait for other threads, etc.
There is no problem associated with this, unless some state is mutated while the thread sleeps, so it wakes up with a different set of values than before going to sleep.
Threads are switched in and out of execution by the CPU all the time, but that does not affect the overall outcome of their execution, assuming no data races or other bugs are present.
It would be unadvisable for one thread to forcibly and synchronously interfere with the execution of another thread. One thread could send an asynchronous message to another requesting that it reschedule itself in some way, but that would be handled by the other thread when it was in a suitable state to do so.
Assuming they communicate using channels that are thread-safe, nothing bad shoudl happen, as the sleeping thread will wake up eventually and grab data from its task queue or see that some semaphore has been set and read the prodced data.
If the threads communicate using nonvolatile variables or direct function calls that change state, that's when Bad Things occur.
I don't know of a way for a thread to forcibly cause another thread to sleep. If two threads are accessing a shared resource (like an input/output queue, which seems likely for you Produce/Consumer example), then both threads may contend for the same lock. The losing thread must wait for the other thread to release the lock if the contention is not the "trylock" variety. The thread that waits is placed into a waiting queue associated with the lock, and is removed from the schedulers run queue. When the winning thread releases the lock, the code checks the queue to see if there are threads still waiting to acquire it. If there are, one is chosen as the winner and is given the lock, and placed in the scheduler run queue.