c++ condition_variable hangs

Hi,

below is my code which I have written to recreate a problem observed in a much larger project. This code recreates the problem in the larger project as is. What i don't understand is that as control reaches cv.wait() in worker thread, the thread then blocks further execution of all threads. (Either no thread is running or the worker thread is in an infinite loop and not letting any context switch to master thread). This happens in both debug mode is Visual Studio and the application itself(.exe).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
// condVarSyncWPredicate.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

#include <thread>
#include <condition_variable>
#include <mutex>
#include <iostream>

std::mutex cv_mutex;
std::condition_variable cv;
bool cv_value;

void createThreads();
void workerThread();
void masterThread();

int main()
{

    createThreads();
    return 0;
}

void createThreads()
{
	std::thread t1(workerThread);
	t1.join();
	std::thread t2(masterThread);
	t2.join();
	return;
}

void workerThread()
{
	int i=0;
	while (true)
	{
		std::cout << "workerThread[" << i << "]" << std::endl;
		std::unique_lock<std::mutex> uq_lck(cv_mutex);
		cv.wait(uq_lck, [] {return cv_value; });
		{
			std::lock_guard<std::mutex> lk(cv_mutex);
			cv_value = false;
		}
		i++;
	}
}

void masterThread()
{
	int i=0;
	while (true)
	{
		std::cout << "masterThread[" << i << "]" << std::endl;
		{
			std::lock_guard<std::mutex> lk(cv_mutex);
			cv_value = true;
		}
		cv.notify_all();
		i++;
	}

}


When I run this code (compiled as executable or in debug mode in Visual Studio), the output I get is:

workerThread[0]

DEBUGing in Visual Studio, I observed in Visual Studio the control reaches the cv.wait() and never even reaches t1.join() using thread debug window.

Please sugesst the cause of this behavior. Ty.
Last edited on
Please use the code format tags to format your code. It's unreadable as presented.

Don't you want masterThread and workerThread to execute concurrently? As it stands, they're serial.
Hi @kbw,

Thanks you for responding. Apologies as this was my first post.

I indeed want them to execute concurrently. How do you deduce that they are serial here...?
> t1.join();
This, in the place that it's in, makes it all serial.
You create one thread and then wait for it to finish.
You never get to create the other thread.
umm, I understood std::thread:join() as a non-blocking way to join the thread to current thread. But looks like that is not the case.

Just to add on to this question, is there a way to join both
workerThread and Master Thread without having to wait for the workerThread to return...?
umm, I understood std::thread:join() as a non-blocking way to join the thread to current thread. But looks like that is not the case.
I'm not sure what you think join() does...
Actually join() waits for the thread to finish.

workerThread and Master Thread without having to wait for the workerThread to return...?
1
2
3
4
5
6
7
8
void createThreads()
{
	std::thread t1(workerThread);
	std::thread t2(masterThread);
	t1.join();
	t2.join();
	return;
}
1
2
3
4
5
6
7
8
void createThreads()
{
	std::thread t1(workerThread);
	std::thread t2(masterThread);
	t1.join();
	t2.join();
	return;
}


This shall resolve the problem if createThreads() & Main() doesn't have to do any other tasks/code following the jon() statement.

But say if the Main() or createThreads were to execute few other lines after join how do I do that..? I can think of only 1 solutions:
> I can dettach the threads instead of joining them and let the workerThread()and masterThread() threads run freely, and periodically check for a terminate condition.. if terminate condition is set, then call std::thread::terminate()
Last edited on
I would suggest that you start the thread at the beginning of main() and join() them at the end. Then you can do whatever you want inbetween.

if terminate condition is set, then call std::thread::terminate()
Iinstead of basically crashing your program consider this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
std::mutex cv_mutex;
std::condition_variable cv;
bool cv_value;

atomic_bool terminate_program = false; // Note

void createThreads();
void workerThread();
void masterThread();

int main()
{
	std::thread t1(workerThread);
	std::thread t2(masterThread);

// Do stuff

	t1.join();
	t2.join();

    return 0;
}

void workerThread()
{
	int i=0;
	while (not terminate_program) // Note
	{
		std::cout << "workerThread[" << i << "]" << std::endl;
		std::unique_lock<std::mutex> uq_lck(cv_mutex);
		cv.wait(uq_lck, [] {return cv_value; });
		{
			std::lock_guard<std::mutex> lk(cv_mutex);
			cv_value = false;
		}
		i++;
	}
}

void masterThread()
{
	int i=0;
	while (not terminate_program) // Note
	{
		std::cout << "masterThread[" << i << "]" << std::endl;
		{
			std::lock_guard<std::mutex> lk(cv_mutex);
			cv_value = true;
		}

if(i > 100) // Example of terminate....
  terminate_program = true;

		cv.notify_all();
		i++;
	}

}

Thank you for the suggestions guys.
Topic archived. No new replies allowed.