I am trying to create a thread that gets notified via the Conditional variable to execute some code. I bounded the thread to a class member function like this:
m_dbSaver = std::thread(std::bind(&ContactLearningApp::DBWorkerThread, this));
m_lk = std::unique_lock<std::mutex>(m_mutex);
m_Processed = true;
Every half a second, I try to run the thread like this:
if (m_sampleClock.getTimeMilliseconds() > 500) {
printf("Save samples to DB\n");
// Wait for worker to finish processing
m_cv.wait(m_lk, [this] {return this->m_Processed; });
// Instruct thread to execute
m_Ready = true;
m_cv.notify_one();
m_sampleClock.reset();
}
My Worker thread looksl ike this:
void ContactLearningApp::DBWorkerThread() {
std::unique_lock<std::mutex> ul(m_mutex);
printf("Start worker thread. \n");
while (true) {
printf("Inside while loop and waiting. \n");
m_cv.wait(ul, [this] {return this->m_Ready; });
printf("Condition passed. \n");
m_Processed = false;
std::cout << "Worker thread processing data. " << std::endl;
m_Processed = true;
ul.unlock();
m_cv.notify_one();
}
}
The worker thread never passes the condition even though I set the m_Ready predicate to be true. If I set the m_Ready variable to be true before I create the thread, the condition passes. Am I doing this correctly?
The first time through the worker loop you have the lock, the 2nd time you don't have the lock.
Wait until notified
The execution of the current thread (which shall
have locked lck's mutex) is blocked until notified.
It needs to be locked.
printf("Start worker thread. \n");
while (true) {
printf("Inside while loop and waiting. \n");
std::unique_lock<std::mutex> ul(m_mutex);
m_cv.wait(ul, [this] {return this->m_Ready; });
printf("Condition passed. \n");
m_Processed = false;
std::cout << "Worker thread processing data. " << std::endl;
m_Processed = true;
ul.unlock();
m_cv.notify_one();
}
This should improve you chance of getting it right.
Related
I'm wanting to have several threads all waiting on a conditional variable (CV) and when the main thread updates a variable they all execute. However, I need the main thread to wait until all these have completed before moving on. The other threads don't end and simply go back around and wait again, so I can't use thread.join() for example.
I've got the first half working, I can trigger the threads, but the main just hangs and doesn't continue. Below is my current code
#include <iostream> // std::cout
#include <thread> // std::thread
#include <mutex> // std::mutex, std::unique_lock
#include <condition_variable> // std::condition_variable
#include <Windows.h>
#define N 3
std::mutex mtx;
std::condition_variable cv;
bool ready = false;
bool finished[N];
void print_id(int id) {
while (1) {
std::unique_lock<std::mutex> lck(mtx); //Try and Lock the Mutex
while (finished[id]) cv.wait(lck); //Wait until finished is false
// ...
std::cout << "thread " << id << '\n';
finished[id] = true; //Set finished to be true. When true, program should continue
}
}
int main()
{
std::thread threads[N];
// spawn 10 threads:
for (int i = 0; i < N; ++i) {
threads[i] = std::thread(print_id, i); //Create n threads
finished[i] = true; //Set default finished to be true
}
std::cout << "N threads ready to race...\n";
for (int i = 0; i < 5; i++) {
std::unique_lock<std::mutex> lck(mtx); //Lock mutex
for (int i = 0; i < N; i++) {
finished[i] = false; //Set finished to false, this will break the CV in each thread
}
cv.notify_all(); //Notify all threads
cv.wait(lck, [] {return finished[0] == true; }); //Wait until all threads have finished (but not ended)
std::cout << "finished, Sleeping for 2s\n";
Sleep(2000);
}
return 0;
}
Thank you.
Edit: I am aware I am only currently checking the status of the finished[0] and not each one. This is done just for simplicity atm and would eventually need to be all of them. I will write a function to manage this later.
You have cv.wait(lck, [] {return finished[0] == true; }); in main thread, but it is not being notified.
You'd need to notify it, and you'd better use another condition_variable for it, not the same as for worker thead notifiecation.
I detach a thread from Class B:
t1 = std::thread(&Class::method, this);
t1.detach();
which as part of it's normal operation waits on a condition variable:
cv.wait(lock);
However, when I close my B application the detached thread remains. How do I stop/clean-up this thread when B::~B() is called?
Try this snippet: Set bool member variable discard_ to true to avoid execution of your scheduled process execution:
std::thread([&](){
std::lock_guard<std::mutex> lock(mutex_);
cv.wait(lock,[](){ return normal_predicate_here || discard_ ;});
if(discard_) return;
// execute scheduled process
}).detach();
Make the other thread cooperate for termination. Non-detached thread makes it easier to terminate cleanly, so that you do not destroy the state accessed by the other thread prematurely:
struct OtherThread {
std::mutex m_;
std::condition_variable c_;
bool stop_ = false;
std::thread t_;
void thread_function() {
for(;;) {
std::unique_lock<std::mutex> l(m_);
while(!stop_ /* || a-message-received */)
c_.wait(l);
if(stop_)
return;
// Process a message.
// ...
// Continue waiting for messages or stop.
}
}
~OtherThread() {
this->stop();
}
void stop() {
{
std::unique_lock<std::mutex> l(m_);
if(stop_)
return;
stop_ = true;
}
c_.notify_one();
t_.join(); // Wait till the thread exited, so that this object can be destroyed.
}
};
I'm looking at this Boost example code for two processes sharing a mutex and condition variable between them:
https://www.boost.org/doc/libs/1_57_0/doc/html/interprocess/synchronization_mechanisms.html
but I don't understand how the mutex-condition variable design here can work.
The initial process calls:
for(int i = 0; i < NumMsg; ++i){
scoped_lock<interprocess_mutex> lock(data->mutex); // Take mutex
if(data->message_in){
data->cond_full.wait(lock); // Wait
}
if(i == (NumMsg-1))
std::sprintf(data->items, "%s", "last message");
else
std::sprintf(data->items, "%s_%d", "my_trace", i);
//Notify to the other process that there is a message
data->cond_empty.notify_one(); // Notify
//Mark message buffer as full
data->message_in = true;
}
and the second process calls:
bool end_loop = false;
do{
scoped_lock<interprocess_mutex> lock(data->mutex); // Take mutex
if(!data->message_in){
data->cond_empty.wait(lock); // Wait
}
if(std::strcmp(data->items, "last message") == 0){
end_loop = true;
}
else{
//Print the message
std::cout << data->items << std::endl;
//Notify the other process that the buffer is empty
data->message_in = false;
data->cond_full.notify_one(); // Notify
}
}
while(!end_loop);
To call wait() or notify() either process must hold the shared mutex, so if one process is on wait() the other surely cannot call notify()?
wait releases the mutex while waiting, so the other thread can acquire the mutex and perform the notify.
Also see the description on https://www.boost.org/doc/libs/1_57_0/doc/html/interprocess/synchronization_mechanisms.html#interprocess.synchronization_mechanisms.conditions.conditions_whats_a_condition.
I'm trying to write a program which uses c++11 threads functionality in order to spawn multiple threads, the main thread must wait for each spawned thread to be finished, and all spawned threads must run in parallel. I've come up with the following approach:
#include <iostream>
#include <stdio.h>
#include <thread>
#include <condition_variable>
#include <mutex>
using namespace std;
class Producer
{
public:
Producer(int a_id):
m_id(a_id),
m_running(false),
m_ready(false),
m_terminate(false)
{
m_id = a_id;
m_thread = thread(&Producer::run, this);
while (!m_ready) {}
}
~Producer() {
terminate();
m_thread.join();
}
void wait() {
unique_lock<mutex> lock(m_waitForRunFinishMutex);
m_cond.wait(lock);
// avoid spurious wake up
if (m_running) {
wait();
}
lock.unlock();
cout << "wait exit " << m_id << endl;
}
void start() {
m_running = true;
m_cond.notify_all();
}
void terminate() {
start();
m_terminate = true;
}
void run() {
m_ready = true;
do {
unique_lock<mutex> lock(m_mutex);
while (!m_running) {
m_cond.wait(lock);
}
if (!m_terminate) {
cout << "running thread: " << m_id << endl;
}
m_running = false;
m_cond.notify_all();
} while (!m_terminate);
}
private:
int m_id;
bool m_running;
bool m_ready;
bool m_terminate;
thread m_thread;
mutex m_mutex;
mutex m_waitForRunFinishMutex;
condition_variable m_cond;
};
The program runs fine when testing with just one thread, i.e the following program:
int main()
{
Producer producer1(1);
producer1.start();
producer1.wait();
return 0;
}
Results in the following output:
running thread: 1
wait exit: 1
However if I test the program with 2 thread, e.g:
int main()
{
Producer producer1(1);
Producer producer2(2);
producer1.start();
producer2.start();
producer1.wait();
producer2.wait();
return 0;
}
I get the following output:
running thread: 2
running thread: 1
wait exit 1
It seems producer2 never get notified (in producer2.wait()), and therefore the program never finishes. Hopefully somebody can point out what I'm missing here.
Thanks everybody for the help in addressing the problem. Eventually the root cause of the problem is described in point (3) of the accepted answer. I've solved this by correcting the wait function as follows:
void wait() {
unique_lock<mutex> lock(m_waitForRunFinishMutex);
while (m_running) {
m_cond.wait(lock);
}
lock.unlock();
}
Here's a quick collection of issues from a glance.
wait() is recursive without unlocking its unique lock (as per the comment from Detonar)
while (!m_ready) {} Is not in a memory barrier (try compiling with some optimization and see what happens!)
If the worker thread completes before wait() is called; there is no check performed before waiting on the condition variable. Since the worker thread is complete; it will never get woken. Clearly you must check to see if the thread can get woken up within the mutex before waiting on the condition variable.
I have NUM_THREADS threads, with the following codes in my thread:
/*
Calculate some_value;
*/
//Critical section to accummulate all thresholds
{
boost::mutex::scoped_lock lock(write_mutex);
T += some_value;
num_threads++;
if (num_threads == NUM_THREADS){
T = T/NUM_THREADS;
READY = true;
cond.notify_all();
num_threads = 0;
}
}
//Wait for average threshold to be ready
if (!READY)
{
boost::unique_lock<boost::mutex> lock(wait_mutex);
while (!READY){
cond.wait(lock);
}
}
//End critical section
/*
do_something;
*/
Basically, I want all the threads to wait for the READY signal before continuing. num_thread is set to 0, and READY is false before threads are created. Once in a while, deadlock occurs. Can anyone help please?
All the boost variables are globally declared as follows:
boost::mutex write_mutex;
boost::mutex wait_mutex;
boost::condition cond;
The code has a race condition on the READY flag (which I assume is just a bool variable). What may happen (i.e. one possible variant of thread execution interleaving) is:
Thread T1: Thread T2:
if (!READY)
{
unique_lock<mutex> lock(wait_mutex); mutex::scoped_lock lock(write_mutex);
while (!READY) /* ... */
{ READY = true;
/* !!! */ cond.notify_all();
cond.wait(lock);
}
}
The code testing the READY flag is not synchronized with the code setting it (note the locks are different for these critical sections). And when T1 is in a "hole" between the flag test and waiting at cond, T2 may set the flag and send a signal to cond which T1 may miss.
The simplest solution is to lock the right mutex for the update of READY and condition notification:
/*...*/
T = T/NUM_THREADS;
{
boost::mutex::scoped_lock lock(wait_mutex);
READY = true;
cond.notify_all();
}
It looks like Boost.Thread's barriers might be what you need.
Here's a working example that averages values provided by several worker threads. Each worker thread uses the same shared barrier (via the accumulator instance) to synchronize each other.
#include <cstdlib>
#include <iostream>
#include <vector>
#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/thread.hpp>
boost::mutex coutMutex;
typedef boost::lock_guard<boost::mutex> LockType;
class Accumulator
{
public:
Accumulator(int count) : barrier_(count), sum_(0), count_(count) {}
void accumulateAndWait(float value)
{
{
// Increment value
LockType lock(mutex_);
sum_ += value;
}
barrier_.wait(); // Wait for other the threads to wait on barrier.
}
void wait() {barrier_.wait();} // Wait on barrier without changing sum.
float sum() {LockType lock(mutex_); return sum_;} // Return current sum
float average() {LockType lock(mutex_); return sum_ / count_;}
// Reset the sum. The barrier is automatically reset when triggered.
void reset() {LockType lock(mutex_); sum_ = 0;}
private:
typedef boost::lock_guard<boost::mutex> LockType;
boost::barrier barrier_;
boost::mutex mutex_;
float sum_;
int count_;
};
/* Posts a value for the accumulator to add and waits for other threads
to do the same. */
void workerFunction(Accumulator& accumulator)
{
// Sleep for a random amount of time before posting value
int randomMilliseconds = std::rand() % 3000;
boost::posix_time::time_duration randomDelay =
boost::posix_time::milliseconds(randomMilliseconds);
boost::this_thread::sleep(randomDelay);
// Post some random value
float value = std::rand() % 100;
{
LockType lock(coutMutex);
std::cout << "Thread " << boost::this_thread::get_id() << " posting "
<< value << " after " << randomMilliseconds << "ms\n";
}
accumulator.accumulateAndWait(value);
float avg = accumulator.average();
// Print a message to indicate this thread is past the barrier.
{
LockType lock(coutMutex);
std::cout << "Thread " << boost::this_thread::get_id() << " unblocked. "
<< "Average = " << avg << "\n" << std::flush;
}
}
int main()
{
int workerThreadCount = 5;
Accumulator accumulator(workerThreadCount);
// Create and launch worker threads
boost::thread_group threadGroup;
for (int i=0; i<workerThreadCount; ++i)
{
threadGroup.create_thread(
boost::bind(&workerFunction, boost::ref(accumulator)));
}
// Wait for all worker threads to finish
threadGroup.join_all();
{
LockType lock(coutMutex);
std::cout << "All worker threads finished\n" << std::flush;
}
/* Pause a bit before exiting, to give worker threads a chance to
print their messages. */
boost::this_thread::sleep(boost::posix_time::seconds(1));
}
I get the following output:
Thread 0x100100f80 posting 72 after 1073ms
Thread 0x100100d30 posting 44 after 1249ms
Thread 0x1001011d0 posting 78 after 1658ms
Thread 0x100100ae0 posting 23 after 1807ms
Thread 0x100101420 posting 9 after 1930ms
Thread 0x100101420 unblocked. Average = 45.2
Thread 0x100100f80 unblocked. Average = 45.2
Thread 0x100100d30 unblocked. Average = 45.2
Thread 0x1001011d0 unblocked. Average = 45.2
Thread 0x100100ae0 unblocked. Average = 45.2
All worker threads finished