How to synchronize this, nicely? - multithreading

Given the following C++11 code fragment:
#include <condition_variable>
#include <mutex>
std::mutex block;
long count;
std::condition_variable cv;
void await()
{
std::unique_lock<std::mutex> lk(block);
if (count > 0)
cv.wait(lk);
}
void countDown()
{
std::lock_guard<std::mutex> lk(block);
if (count > 0)
{
count--;
if (count==0) cv.notify_all();
}
}
If it is not clear what I am trying to accomplish, I am wanting calls to await to pause the calling thread while count is greater than 0, and if it has already been reduced to zero, then it should not pause at all. Other threads may call countDown() which will wake all threads that had previously called await.
The above code seems to work in all cases that I've tried, but I have this nagging doubt about it, because it seems to me like there is a possibility for unexpected behavior if the thread calling await() just happens to get preempted immediately after its condition test has been evaluated and just before the thread is actually suspended by the cv.wait() call, and if the countDown function is getting called at this time, and the count equals 0, then it would issue a notify to the condition variable, IF it were actually already waiting on it... but the thread calling await hasn't hit the cv.wait() call yet, so when the thread calling await resumes, it stops at the cv.wait() call and waits indefinitely.
I actually haven't seen this happen yet in practice, but I would like to harden the code against the eventuality.

It is good that you are thinking about these possibilities. But in this case your code is correct and safe.
If await gets preempted immediately after its condition test has been evaluated and just before the thread is actually suspended by the cv.wait() call, and if the countDown function is getting called at this time, the latter thread will block while trying to obtain the block mutex until await actually calls cv.wait(lk).
The call to cv.wait(lk) implicitly releases the lock on block, and thus now another thread can obtain the lock on block in countDown(). And as long as a thread holds the lock on block in countDown() (even after cv.notify_all() is called), the await thread can not return from cv.wait(). The await thread implicitly blocks on trying to re-lock block during the return from cv.wait().
Update
I did make a rookie mistake while reviewing your code though <blush>.
cv.wait(lk) may return spuriously. That is, it may return even though it hasn't been notified. To guard against this you should place your wait under a while loop, instead of under an if:
void await()
{
std::unique_lock<std::mutex> lk(block);
while (count > 0)
cv.wait(lk);
}
Now if the wait returns spuriously, it re-checks the condition, and if still not satisfied, waits again.

Related

Is Calling the `Wait()` method of `sync.Cond` Concurrently, Safe?

Is calling the Wait() method of sync.Cond safe when according to the documentation, it performs an Unlock() first?
Assume we are checking for a condition to be met:
func sample() {
cond = &sync.Cond{L: &sync.Mutex{}} // accessible by other parts of program
go func() {
cond.L.Lock()
for !condition() {
cond.Wait()
}
// do stuff ...
cond.L.Unlock()
}()
go func() {
cond.L.Lock()
mutation()
cond.L.Unlock()
cond.Signal()
}()
}
And:
func condition() bool {
// assuming someSharedState is a more complex state than just a bool
return someSharedState
}
func mutation() {
// assuming someSharedState is a more complex state than just a bool
// (A) state mutation on someSharedState
}
Since Wait() performs an Unlock, should (A) has a locking of it's own? Or being atomic?
Yes it is safe to call Wait even when it calls L.Unlock() first but it is essential that you acquired the lock before calling Wait and before checking your condition since, in this situation, both are not thread safe.
Wait atomically unlocks c.L and suspends execution of the calling goroutine. After later resuming execution, Wait locks c.L before returning.
The goroutine that calls Wait acquired the lock, checked the condition and found it to be unsatisfactory.
Now it waits but in order to allow for changes of the condition it needs to give the lock back. Wait does that automatically for you and then suspends the goroutine.
Now changes of the condition can happen and eventually the goroutine is awoken by Broadcast or Signal. It then acquires the lock to check the condition once again (This must happen one-by-one for each waiting goroutine or else there would be no way telling how many goroutines are running around freely now).

How to implement a re-usable thread barrier with std::atomic

I have N threads performing various task and these threads must be regularly synchronized with a thread barrier as illustrated below with 3 thread and 8 tasks. The || indicates the temporal barrier, all threads have to wait until the completion of 8 tasks before starting again.
Thread#1 |----task1--|---task6---|---wait-----||-taskB--| ...
Thread#2 |--task2--|---task5--|-------taskE---||----taskA--| ...
Thread#3 |-task3-|---task4--|-taskG--|--wait--||-taskC-|---taskD ...
I couldn’t find a workable solution, thought the little book of Semaphores http://greenteapress.com/semaphores/index.html was inspiring. I came up with a solution using std::atomic shown below which “seems” to be working using three std::atomic.
I am worried about my code breaking down on corner cases hence the quoted verb. So can you share advise on verification of such code? Do you have a simpler fool proof code available?
std::atomic<int> barrier1(0);
std::atomic<int> barrier2(0);
std::atomic<int> barrier3(0);
void my_thread()
{
while(1) {
// pop task from queue
...
// and execute task
switch(task.id()) {
case TaskID::Barrier:
barrier2.store(0);
barrier1++;
while (barrier1.load() != NUM_THREAD) {
std::this_thread::yield();
}
barrier3.store(0);
barrier2++;
while (barrier2.load() != NUM_THREAD) {
std::this_thread::yield();
}
barrier1.store(0);
barrier3++;
while (barrier3.load() != NUM_THREAD) {
std::this_thread::yield();
}
break;
case TaskID::Task1:
...
}
}
}
Boost offers a barrier implementation as an extension to the C++11 standard thread library. If using Boost is an option, you should look no further than that.
If you have to rely on standard library facilities, you can roll your own implementation based on std::mutex and std::condition_variable without too much of a hassle.
class Barrier {
int wait_count;
int const target_wait_count;
std::mutex mtx;
std::condition_variable cond_var;
Barrier(int threads_to_wait_for)
: wait_count(0), target_wait_count(threads_to_wait_for) {}
void wait() {
std::unique_lock<std::mutex> lk(mtx);
++wait_count;
if(wait_count != target_wait_count) {
// not all threads have arrived yet; go to sleep until they do
cond_var.wait(lk,
[this]() { return wait_count == target_wait_count; });
} else {
// we are the last thread to arrive; wake the others and go on
cond_var.notify_all();
}
// note that if you want to reuse the barrier, you will have to
// reset wait_count to 0 now before calling wait again
// if you do this, be aware that the reset must be synchronized with
// threads that are still stuck in the wait
}
};
This implementation has the advantage over your atomics-based solution that threads waiting in condition_variable::wait should get send to sleep by your operating system's scheduler, so you don't block CPU cores by having waiting threads spin on the barrier.
A few words on resetting the barrier: The simplest solution is to just have a separate reset() method and have the user ensure that reset and wait are never invoked concurrently. But in many use cases, this is not easy to achieve for the user.
For a self-resetting barrier, you have to consider races on the wait count: If the wait count is reset before the last thread returned from wait, some threads might get stuck in the barrier. A clever solution here is to not have the terminating condition depend on the wait count variable itself. Instead you introduce a second counter, that is only increased by the thread calling the notify. The other threads then observe that counter for changes to determine whether to exit the wait:
void wait() {
std::unique_lock<std::mutex> lk(mtx);
unsigned int const current_wait_cycle = m_inter_wait_count;
++wait_count;
if(wait_count != target_wait_count) {
// wait condition must not depend on wait_count
cond_var.wait(lk,
[this, current_wait_cycle]() {
return m_inter_wait_count != current_wait_cycle;
});
} else {
// increasing the second counter allows waiting threads to exit
++m_inter_wait_count;
cond_var.notify_all();
}
}
This solution is correct under the (very reasonable) assumption that all threads leave the wait before the inter_wait_count overflows.
With atomic variables, using three of them for a barrier is simply overkill that only serves to complicate the issue. You know the number of threads, so you can simply atomically increment a single counter every time a thread enters the barrier, and then spin until the counter becomes greater or equal to N. Something like this:
void barrier(int N) {
static std::atomic<unsigned int> gCounter = 0;
gCounter++;
while((int)(gCounter - N) < 0) std::this_thread::yield();
}
If you don't have more threads than CPU cores and a short expected waiting time, you might want to remove the call to std::this_thread::yield(). This call is likely to be really expensive (more than a microsecond, I'd wager, but I haven't measured it). Depending on the size of your tasks, this may be significant.
If you want to do repeated barriers, just increment the N as you go:
unsigned int lastBarrier = 0;
while(1) {
switch(task.id()) {
case TaskID::Barrier:
barrier(lastBarrier += processCount);
break;
}
}
I would like to point out that in the solution given by #ComicSansMS ,
wait_count should be reset to 0 before executing cond_var.notify_all();
This is because when the barrier is called a second time the if condition will always fail, if wait_count is not reset to 0.

CoGetInterfaceAndReleaseStream let my thread hangs

UINT __stdcall CExternal::WorkThread( void * pParam)
{
HRESULT hr;
CTaskBase* pTask;
CComPtr<IHTMLDocument3> spDoc3;
CExternal* pThis = reinterpret_cast<CExternal*>(pParam);
if (pThis == NULL)
return 0;
// Init the com
::CoInitializeEx(0,COINIT_APARTMENTTHREADED);
hr = ::CoGetInterfaceAndReleaseStream(
pThis->m_pStream_,
IID_IHTMLDocument3,
(void**)&spDoc3);
if(FAILED(hr))
return 0;
while (pThis->m_bShutdown_ == 0)
{
if(pThis->m_TaskList_.size())
{
pTask = pThis->m_TaskList_.front();
pThis->m_TaskList_.pop_front();
if(pTask)
{
pTask->doTask(spDoc3); //do my custom task
delete pTask;
}
}
else
{
Sleep(10);
}
}
OutputDebugString(L"start CoUninitialize\n");
::CoUninitialize(); //release com
OutputDebugString(L"end CoUninitialize\n");
return 0;
}
The above the code that let my thread hang, the only output is "start CoUninitialize".
m_hWorker_ = (HANDLE)_beginthreadex(NULL, 0, WorkThread, this, 0, 0);
This code starts my thread, but the thread can't exit safely, so it waits. What the problem with this code?
The problem is not in this code, although it violates core COM requirements. Which says that you should release interface pointers when you no longer use them, calling IUnknown::Release(), and that an apartment-threaded thread must pump a message loop. Especially the message loop is important, you'll get deadlock when the owner thread of a single-threaded object (like a browser) is not pumping.
CoUninitialize() is forced to clean up the interface pointer wrapped by spDoc3 since you didn't do this yourself. It is clear from the code that the owner of the interface pointer actually runs on another thread, something to generally keep in mind since that pretty much defeats the point of starting your own worker thread. Creating your own STA thread doesn't fix this, it is still the wrong thread.
So the proxy needs to context switch to the apartment that owns the browser object. With the hard requirement that this apartment pumps a message loop so that the call can be dispatched on the right thread in order to safely call the Release() function. With very high odds that this thread isn't pumping messages anymore when your program is shutting down. Something you should be able to see in the debugger, locate the owner thread in the Debug + Windows + Threads window and see what it is doing.
Deadlock is the common outcome. The only good way to fix it is to shut down threads in the right order, this one has to shut down before the thread that owns the browser object. Shutting down a multi-threaded program cleanly can be quite difficult when threads have an interdependency like this. The inspiration behind the C++11 std::quick_exit() addition.

pthread_cond_wait never unblocking - thread pools

I'm trying to implement a sort of thread pool whereby I keep threads in a FIFO and process a bunch of images. Unfortunately, for some reason my cond_wait doesn't always wake even though it's been signaled.
// Initialize the thread pool
for(i=0;i<numThreads;i++)
{
pthread_t *tmpthread = (pthread_t *) malloc(sizeof(pthread_t));
struct Node* newNode;
newNode=(struct Node *) malloc(sizeof(struct Node));
newNode->Thread = tmpthread;
newNode->Id = i;
newNode->threadParams = 0;
pthread_cond_init(&(newNode->cond),NULL);
pthread_mutex_init(&(newNode->mutx),NULL);
pthread_create( tmpthread, NULL, someprocess, (void*) newNode);
push_back(newNode, &threadPool);
}
for() //stuff here
{
//...stuff
pthread_mutex_lock(&queueMutex);
struct Node *tmpNode = pop_front(&threadPool);
pthread_mutex_unlock(&queueMutex);
if(tmpNode != 0)
{
pthread_mutex_lock(&(tmpNode->mutx));
pthread_cond_signal(&(tmpNode->cond)); // Not starting mutex sometimes?
pthread_mutex_unlock(&(tmpNode->mutx));
}
//...stuff
}
destroy_threads=1;
//loop through and signal all the threads again so they can exit.
//pthread_join here
}
void *someprocess(void* threadarg)
{
do
{
//...stuff
pthread_mutex_lock(&(threadNode->mutx));
pthread_cond_wait(&(threadNode->cond), &(threadNode->mutx));
// Doesn't always seem to resume here after signalled.
pthread_mutex_unlock(&(threadNode->mutx));
} while(!destroy_threads);
pthread_exit(NULL);
}
Am I missing something? It works about half of the time, so I would assume that I have a race somewhere, but the only thing I can think of is that I'm screwing up the mutexes? I read something about not signalling before locking or something, but I don't really understand what's going on.
Any suggestions?
Thanks!
Firstly, your example shows you locking the queueMutex around the call to pop_front, but not round push_back. Typically you would need to lock round both, unless you can guarantee that all the pushes happen-before all the pops.
Secondly, your call to pthread_cond_wait doesn't seem to have an associated predicate. Typical usage of condition variables is:
pthread_mutex_lock(&mtx);
while(!ready)
{
pthread_cond_wait(&cond,&mtx);
}
do_stuff();
pthread_mutex_unlock(&mtx);
In this example, ready is some variable that is set by another thread whilst that thread holds a lock on mtx.
If the waiting thread is not blocked in the pthread_cond_wait when pthread_cond_signal is called then the signal will be ignored. The associated ready variable allows you to handle this scenario, and also allows you to handle so-called spurious wake-ups where the call to pthread_cond_wait returns without a corresponding call to pthread_cond_signal from another thread.
I'm not sure, but I think you don't have to (you must not) lock the mutex in the thread pool before calling pthread_cond_signal(&(tmpNode->cond)); , otherwise, the thread which is woken up won't be able to lock the mutex as part of pthread_cond_wait(&(threadNode->cond), &(threadNode->mutx)); operation.

Problem in suspending 2 threads at the same time in MFC!

I am learning about threading and multithreading..so i just created a small application in which i will update
the progressbar and a static text using threading.I vl get two inputs from the user, start and end values
for how long the loop should rotate.I have 2threads in my application.
Thread1- to update the progressbar(according to the loop) the static text which will show the count(loop count).
Thread2 - to update the another static text which will just diplay a name
Basically if the user clicks start, the progressbar steps up and at the same time filecount and the name are displayed parallely.
There's is another operation where if the user clicks pause it(thread) has to suspend until the user clicks resume.
The problem is,the above will not work(will not suspend and resume) for both thread..but works for a singlw thread.
Please check the code to get an idea and reply me what can done!
on button click start
void CThreadingEx3Dlg::OnBnClickedStart()
{
m_ProgressBar.SetRange(start,end);
myThread1 = AfxBeginThread((AFX_THREADPROC)MyThreadFunction1,this);
myThread2 = AfxBeginThread((AFX_THREADPROC)MyThreadFunction2,this);
}
thread1
UINT MyThreadFunction1(LPARAM lparam)
{
CThreadingEx3Dlg* pthis = (CThreadingEx3Dlg*)lparam;
for(int intvalue =pthis->start;intvalue<=pthis->end; ++intvalue)
{
pthis->SendMessage(WM_MY_THREAD_MESSAGE1,intvalue);
}
return 0;
}
thread1 function
LRESULT CThreadingEx3Dlg::OnThreadMessage1(WPARAM wparam,LPARAM lparam)
{
int nProgress= (int)wparam;
m_ProgressBar.SetPos(nProgress);
CString strStatus;
strStatus.Format(L"Thread1:Processing item: %d", nProgress);
m_Static.SetWindowText(strStatus);
Sleep(100);
return 0;
}
thread2
UINT MyThreadFunction2(LPARAM lparam)
{
CThreadingEx3Dlg* pthis = (CThreadingEx3Dlg*)lparam;
for(int i =pthis->start;i<=pthis->end;i++)
{
pthis->SendMessage(WM_MY_THREAD_MESSAGE2,i);
}
return 0;
}
thread2 function
LRESULT CThreadingEx3Dlg::OnThreadMessage2(WPARAM wparam,LPARAM lparam)
{
m_Static1.GetDlgItem(IDC_STATIC6);
m_Static1.SetWindowTextW(L"Thread2 Running");
Sleep(100);
m_Static1.SetWindowTextW(L"");
Sleep(100);
return TRUE;
}
void CThreadingEx3Dlg::OnBnClickedPause()
{
// TODO: Add your control notification handler code here
if(!m_Track)
{
m_Track = TRUE;
GetDlgItem(IDCANCEL)->SetWindowTextW(L"Resume");
myThread1->SuspendThread();
WaitForSingleObject(myThread1->m_hThread,INFINITE);
myThread2->SuspendThread();
m_Static.SetWindowTextW(L"Paused..");
}
else
{
m_Track = FALSE;
GetDlgItem(IDCANCEL)->SetWindowTextW(L"Pause");
myThread1->ResumeThread();
myThread2->ResumeThread();
/*myEventHandler.SetEvent();
WaitForSingleObject(myThread1->m_hThread,INFINITE);*/
}
}
I thought I should summarize some of the discussion in the comments into an answer.
In Windows programming, you should never try to manipulate a GUI control from a background thread, as doing so can cause your program to deadlock . This means only the main thread should ever touch elements of the GUI. (Technically, what matters is which thread created the control, but it's not common to create controls in background threads).
This requirement is detailed in Joe Newcomer's article on worker threads (see "Worker Threads and the GUI II: Don't Touch the GUI").
You are using SendMessage in your thread procedures. This causes the appropriate message handler for the target control to be invoked, but in the thread that called SendMessage. In your case, that means the background threads run the message handlers and therefore update the progress bar and label.
The alternative is to use PostMessage. This causes the message to be added to a queue to be processed by the main thread's message loop. When the main thread gets to run, it processes the messages in the order they were added to the queue, calling the message handlers itself. Since the main thread owns the windows, it is safe for it to update the controls.
You should also beware that SuspendThread and ResumeThread are tricky to get right. You might want to read this section of Joe Newcomer's article, which describes some of the dangers.
Tasks like this are often better achieved by using a timer. This is a mechanism for having the operating system notify your program when a particular amount of time has passed. You could implement this with a timer as below:
BEGIN_MESSAGE_MAP(CThreadingEx3Dlg, CDialog)
ON_WM_DESTROY()
ON_WM_TIMER()
END_MESSAGE_MAP()
void CThreadingEx3Dlg::OnTimer(UINT_PTR nTimerID)
{
static int progress = 0;
if (nTimerID == 1)
{
m_ProgressBar.SetPos(progress);
CString strStatus;
strStatus.Format(_T("Processing item: %d"), progress);
m_Static.SetWindowText(strStatus);
progress++;
if (progress > end) // If we've reached the end of the updates.
KillTimer(1);
}
}
BOOL CThreadingEx3Dlg::OnInitDialog()
{
// ... initialize controls, etc, as necessary.
SetTimer(1, 100, 0);
}
void CThreadingEx3Dlg::OnDestroy()
{
KillTimer(1);
}
If you want both updates handled at the same time, they can use the same timer. If they need to happen at different times (such as one at a 100 ms interval and another at a 150 ms interval) then you can call SetTimer twice with different IDs. To pause the action, call KillTimer. To resume it, call SetTimer again.
Multi-threading and message queuing is quite a complex game. When you SendMessage from ThreadA to the same thread then it just calls the message handler. If you do it from ThreadA to another thread (ThreadB) then it gets more complicated. ThreadA then posts a message to the ThreadB's message queue and waits on a signal to say that ThreadB has finished processing the message and sent the return value. This raises an instant problem. If ThreadB is not pumping messages then you have a deadlock as the message in ThreadB's will never get "dispatched". This also raises an EVEN bigger problem. If ThreadB's message needs to send a message to a control created in ThreadA then you have a massive architectural problem. As ThreadA is currently suspended waiting for ThreadB to return and ThreadB is suspended waiting for ThreadA to return. Nothing will happen ... They will both sit suspended.
Thats about it really. Its pretty easy as long as you bear these issues in mind. ie It absoloutely IS possible despite what the others have said.
In general though your threading is pretty pointless because you straight away send a message to the main thread to do some processing. Why bother starting the threads in the first place. You may as well not bother because the threads will just sit there waiting for the main thread to return.
Why do you "WaitForSingleObject" anyway when you suspend the first thread? Why not just suspend them both.
All round, though, you aren't giving enough information about what you are doing to say exactly whats going on. What happens when you click pause, for example?
Windows will not operate properly when more than one thread interacts with the GUI. You'll need to reorganize your program so that does not happen.

Resources