Boost Condition Variable with multiple threads - c++

In my program, I have two basic threads. The first one is the main thread and the second is a Tcp server thread. The TCP server will listen for requests ,and for each request it will create a corresponding thread, each of the newly created threads should start working until they reach a certain point where they have to wait for an indication from the main thread. To solve this issue I am implementing a condition variable using Boost 1.49.
My main problem is whenever any of the newly created threads reach the point of the condition variable my whole program freezes.
For more information, please check:
Boost 1.49 Condition Variable issue
Until now I didn't receive any positive response, and I am not able to solve the problem.
Thanks a lot.

I haven't looked at your other question (too much code)
In general, you have to await/signal a condition under the corresponding mutex, though.
Here's a demonstration using a group of 10 workers that await a start signal:
See it Live On Coliru
#include <boost/thread.hpp>
#include <boost/optional/optional_io.hpp>
/////////////////////////
// start condition logic
boost::mutex mx;
boost::condition_variable cv;
static bool ok_to_start = false;
void await_start_condition()
{
boost::unique_lock<boost::mutex> lk(mx);
cv.wait(lk, [] { return ok_to_start; });
}
void signal_start_condition()
{
boost::lock_guard<boost::mutex> lk(mx);
ok_to_start = true;
cv.notify_all();
}
/////////////////////////
// workers
static boost::optional<int> shared_secret;
void worker(int id)
{
await_start_condition();
// demo worker implementation
static boost::mutex console_mx;
boost::lock_guard<boost::mutex> lk(console_mx);
std::cout << "worker " << id << ": secret is " << shared_secret << "\n";
}
int main()
{
boost::thread_group threads;
for (int i = 0; i<10; i++)
threads.create_thread(boost::bind(worker, i));
// demo - initialize some state before thread start
shared_secret = 42;
// signal threads can start
signal_start_condition();
// wait for all threads to finish
threads.join_all();
}
In case of C++03 you can replace the lambda with a hand-written predicate: Live On Coliru
namespace /* anon detail */
{
bool ok_to_start_predicate() { return ok_to_start; }
}
void await_start_condition()
{
boost::unique_lock<boost::mutex> lk(mx);
cv.wait(lk, ok_to_start_predicate);
}
Or you can use Boost Lambda/Boost Phoenix to do the trick for you: Live On Coliru
#include <boost/phoenix.hpp>
void await_start_condition()
{
boost::unique_lock<boost::mutex> lk(mx);
cv.wait(lk, boost::phoenix::cref(ok_to_start));
}

Related

Why is std::mutex taking a long, highly irregular amount of time to be shared?

This code demonstrates that the mutex is being shared between two threads, but one thread has it nearly all of the time.
#include <thread>
#include <mutex>
#include <iostream>
#include <unistd.h>
int main ()
{
std::mutex m;
std::thread t ([&] ()
{
while (true)
{
{
std::lock_guard <std::mutex> thread_lock (m);
sleep (1); // or whatever
}
std::cerr << "#";
std::cerr.flush ();
}
});
while (true)
{
std::lock_guard <std::mutex> main_lock (m);
std::cerr << ".";
std::cerr.flush ();
}
}
Compiled with g++ 7.3.0 on Ubuntu 18.04 4.15.0-23-generic.
The output is a mix of both # and . characters, showing that the mutex is being shared, but the pattern is surprising. Typically something like this:
.......#####..........................##################......................##
i.e. the thread_lock locks the mutex for a very long time. After several or even tens of seconds, the main_lock receives control (briefly) then the thread_lock gets it back and keeps it for ages. Calling std::this_thread::yield() doesn't change anything.
Why are the two mutexes not equally likely to gain the lock, and how can I make the mutex be shared in a balanced fashion?
std::mutex isn't designed to be fair. It doesn't guarantee that the order of locking is kept, you're either lucky to get the lock or not.
If you want more fairness, consider using a std::condition_variable like so :
#include <thread>
#include <mutex>
#include <iostream>
#include <condition_variable>
#include <unistd.h>
int main ()
{
std::mutex m;
std::condition_variable cv;
std::thread t ([&] ()
{
while (true)
{
std::unique_lock<std::mutex> lk(m);
std::cerr << "#";
std::cerr.flush ();
cv.notify_one();
cv.wait(lk);
}
});
while (true)
{
std::unique_lock<std::mutex> lk(m);
std::cerr << ".";
std::cerr.flush ();
cv.notify_one();
cv.wait(lk);
}
}
Making std::mutex fair would have a cost. And in C++ you don't pay for what you don't ask for.
You could write a locking object where the party releasing the lock cannot be the next one to get it. More advanced, you could write one where this only occurs if someone else is waiting.
Here is a quick, untested stab at a fair mutex:
struct fair_mutex {
void lock() {
auto l = internal_lock();
lock(l);
}
void unlock() {
auto l = internal_lock();
in_use = false;
if (waiting != 0) {
loser=std::this_thread::get_id();
} else {
loser = {};
}
cv.notify_one();
}
bool try_lock() {
auto l = internal_lock();
if (in_use) return false;
lock(l);
return true;
}
private:
void lock(std::unique_lock<std::mutex>&l) {
++waiting;
cv.wait( l, [&]{ return !in_use && std::this_thread::get_id() != loser; } );
in_use = true;
--waiting;
}
std::unique_lock<std::mutex> internal_lock() const {
return std::unique_lock<std::mutex>(m);
}
mutable std::mutex m;
std::condition_variable cv;
std::thread::id loser;
bool in_use = false;
std::size_t waiting = 0;
};
it is "fair" in that if you have two threads contending over a resource, they will take turns. If someone is waiting on a lock, anyone giving up the lock won't grab it again.
This is, however, threading code. So I might read it over, but I wouldn't trust my first attempt to write anything.
You could extend this (at increasing cost) to be n-way fair (or even omega-fair) where if there are up to N elements waiting, they all get their turn before the releasing thread gets another chance.

How to wait for multiple threads to finish (with c++11 threads)?

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.

Can multiple threads join the same boost::thread?

pthreads has undefined behavior if multiple threads try to join the same thread:
If multiple threads simultaneously try to join with the same thread,
the results are undefined.
Is the same true for boost::threads? The documentation does not appears to specify this.
If it is undefined, then what would be a clean way for multiple threads to wait on one thread completing?
If it is undefined, then what would be a clean way for multiple threads to wait on one thread completing?
The clean way would be for that one thread to inform the others that it is complete. A packaged_task contains a future which can be waited on, which can help us here.
Here's one way of doing that. I have used std::thread and std::packaged_task, but you could use the boost equivalents just as well.
#include <thread>
#include <mutex>
#include <future>
#include <vector>
#include <iostream>
void emit(const char* msg) {
static std::mutex m;
std::lock_guard<std::mutex> l(m);
std::cout << msg << std::endl;
std::cout.flush();
}
int main()
{
using namespace std;
auto one_task = std::packaged_task<void()>([]{
emit("waiting...");
std::this_thread::sleep_for(std::chrono::microseconds(500));
emit("wait over!");
});
// note: convert future to a shared_future so we can pass it
// to two subordinate threads simultaneously
auto one_done = std::shared_future<void>(one_task.get_future());
auto one = std::thread(std::move(one_task));
std::vector<std::thread> many;
many.emplace_back([one_done] {
one_done.wait();
// do my thing here
emit("starting thread 1");
});
many.emplace_back([one_done] {
one_done.wait();
// do my thing here
emit("starting thread 2");
});
one.join();
for (auto& t : many) {
t.join();
}
cout << "Hello, World" << endl;
return 0;
}
expected output:
waiting...
wait over!
starting thread 2
starting thread 1
Hello, World
I ended up using a boost::condition_variable... roughly:
class thread_wrapper {
boost::mutex mutex;
boost::condition_variable thread_done_condition;
bool thread_done = false;
void the_func() {
// ...
// end of the thread
{
boost:unique_lock<boost::mutex> lock(mutex);
thread_done = true;
}
thread_done_condition.notify_all();
}
void wait_until_done() {
boost::unique_lock<boost::mutex> lock(mutex);
thread_done_condition.wait(lock, [this]{ return thread_done; });
}
}
Then multiple callers can safely call wait_until_done().
It strikes me now that something like the following would also have worked:
class thread_wrapper {
public:
thread_wrapper() : thread([this]() { this->the_func(); }) { }
void wait_until_done() {
boost::unique_lock<boost::mutex> lock(join_mutex);
thread.join();
}
private:
void the_func() {
// ...
}
boost::mutex join_mutex;
boost::thread thread;
}

C++11: condition variable only works for once

I have this piece of code:
std::unique_lock<std::mutex> lock(m_mutex);
for(;;)
{
// wait for input notification
m_event.wait(lock);
// if there is an input pin doesn't have any data, just wait
for(DataPinIn* ptr:m_in_ports)
if(ptr->m_data_dup==NULL)
continue;
// do work
Work(&m_in_ports,&m_out_ports);
// this might need a lock, we'll see
for(DataPinIn* ptr:m_in_ports)
{
// reduce the data refcnt before we lose it
ptr->FreeData();
ptr->m_data_dup=NULL;
std::cout<<"ptr:"<<ptr<<"set to 0\n";
}
}
in which m_event is a condition_variable.
It waits for notification from another thread and then does some works. But I found out that this only succeeds for the first time and it blocks on m_event.wait(lock) forever, no matter how many times m_event.notify_one() is called. How should I solve this?
Thanks in advance.
You are experiencing the common scenario 'spurious wakeup' (please consult wiki) which condition_variable is desgined to solve.
Please read the sample code in this article: http://www.cplusplus.com/reference/condition_variable/condition_variable/.
Usually condition_variable must be used together with a certain variable to avoid spurious wakeups; that's how the synchronization method is named.
Below is a better piece of sample code:
#include <condition_variable>
#include <mutex>
#include <thread>
#include <iostream>
#include <queue>
#include <chrono>
int main()
{
std::queue<int> produced_nums;
std::mutex m;
std::condition_variable cond_var;
bool done = false;
bool notified = false;
std::thread producer([&]() {
for (int i = 0; i < 5; ++i) {
std::this_thread::sleep_for(std::chrono::seconds(1));
std::unique_lock<std::mutex> lock(m);
std::cout << "producing " << i << '\n';
produced_nums.push(i);
notified = true;
cond_var.notify_one();
}
done = true;
cond_var.notify_one();
});
std::thread consumer([&]() {
std::unique_lock<std::mutex> lock(m);
while (!done) {
while (!notified) { // loop to avoid spurious wakeups
cond_var.wait(lock);
}
while (!produced_nums.empty()) {
std::cout << "consuming " << produced_nums.front() << '\n';
produced_nums.pop();
}
notified = false;
}
});
producer.join();
consumer.join();
}
It turns out that a flag variable ruined everything and the threading part is working correctly.

Multithreading and using events

My program has three threads, and I am trying to learn about synchronization and thread safety. Below I outline what the different threads do, but I would like to learn how to use events instead to trigger each process in the different threads instead of infinitely reading (which is giving me concurrency issues).
Googling throws up many options but I'm not sure what is best to implement in this case - could you point the direction to a standard method/event that I could learn to best implement this?
I am doing this on VS 2012, and ideally I would not use external libraries e.g. boost.
Thread 1: receives a message and pushes it into a global queue, queue<my_class> msg_in.
Thread 2: on infinite loop (i.e. while(1) ); waits till if (!msg_in.empty()), does some processing, and pushes it into a global map<map<queue<my_class>>> msg_out.
while (1)
{
if (!msg_in.empty())
{
//processes
msg_map[i][j].push(); //i and j are int (irrelevant here)
}
}
Thread 3:
while (1)
{
if (msg_map.find(i) != msg_map.end())
{
if (!msg_map[i].find(j)->second.empty())
{
//processes
}
}
}
Your problems is a producer consumer problem. You can use condition variables for your events. There is one example of it here: http://en.cppreference.com/w/cpp/thread/condition_variable
I have adapted it to your example if your need it.
#include "MainThread.h"
#include <iostream>
#include <string>
#include <thread>
#include <mutex>
#include <atomic>
#include <condition_variable>
std::mutex m;
std::condition_variable cv;
bool ready = false;
bool processed = false;
void worker_thread(unsigned int threadNum)
{
// Wait until main() sends data
{
std::unique_lock<std::mutex> lk(m);
cv.wait(lk, []{return ready;});
}
std::cout << "Worker thread "<<threadNum <<" is processing data"<<std::endl;
// Send data back to main()
{
std::lock_guard<std::mutex> lk(m);
processed = true;
std::cout << "Worker thread "<< threadNum <<" signals data processing completed\n";
}
cv.notify_one();
}
int initializeData()
{
// send data to the worker thread
{
std::lock_guard<std::mutex> lk(m);
ready = true;
std::cout << "Data initialized"<<std::endl;
}
cv.notify_one();
return 0;
}
int consumerThread(unsigned int nbThreads)
{
std::atomic<unsigned int> nbConsumedthreads=0;
while (nbConsumedthreads<nbThreads)
{
std::unique_lock<std::mutex> lk(m);
cv.wait(lk, []{return processed;});
std::cout<<"Data processed counter="<<nbConsumedthreads << " "<< std::endl;
++nbConsumedthreads;
cv.notify_one();
}
return 0;
}
int main()
{
const unsigned int nbThreads=3;
std::thread worker1(worker_thread,1);
std::thread worker2(worker_thread,2);
std::thread worker3(worker_thread,3);
std::thread init(initializeData);
std::thread consume(consumerThread, nbThreads);
worker1.join();
worker2.join();
worker3.join();
init.join();
consume.join();
return 0;
}
Hope that helps, tell me if you need more info.