What is boost:barrier, how to use this kind of boost method. Could you give me a clear example since I found the examples on the following:
bool wait()
{
boost::mutex::scoped_lock lock(m_mutex);
unsigned int gen = m_generation;
if (--m_count == 0)
{
m_generation++;
m_count = m_threshold;
m_cond.notify_all();
return true;
}
while (gen == m_generation)
m_cond.wait(lock);
return false;
}
In the above codes: m_cond.notify_all();is to enter into other waiting threads?
Could you tell me clearly about barrier functionality? Thank you.
notify_all, notified awaiting threads.
A barrier is a simple concept. Also known as a rendezvous, it is a
synchronization point between multiple threads. The barrier is
configured for a particular number of threads (n), and as threads
reach the barrier they must wait until all n threads have arrived.
Once the n-th thread has reached the barrier, all the waiting threads
can proceed, and the barrier is reset.
Simple example. value of the current will be outputed only when 3 threads call wait function on barrier.
#include <boost/thread.hpp>
#include <boost/thread/barrier.hpp>
#include <boost/bind.hpp>
#include <boost/atomic.hpp>
boost::mutex io_mutex;
void thread_fun(boost::barrier& cur_barier, boost::atomic<int>& current)
{
++current;
cur_barier.wait();
boost::lock_guard<boost::mutex> locker(io_mutex);
std::cout << current << std::endl;
}
int main()
{
boost::barrier bar(3);
boost::atomic<int> current(0);
boost::thread thr1(boost::bind(&thread_fun, boost::ref(bar), boost::ref(current)));
boost::thread thr2(boost::bind(&thread_fun, boost::ref(bar), boost::ref(current)));
boost::thread thr3(boost::bind(&thread_fun, boost::ref(bar), boost::ref(current)));
thr1.join();
thr2.join();
thr3.join();
}
Related
This question already has answers here:
Why do you need a while loop while waiting for a condition variable
(4 answers)
Closed 1 year ago.
Why is it necessary to use while() with std::condition_variable::wait()
in this code:
#include <iostream> // std::cout
#include <thread> // std::thread
#include <mutex> // std::mutex, std::unique_lock
#include <condition_variable> // std::condition_variable
std::mutex mtx;
std::condition_variable cv;
bool ready = false;
void print_id (int id) {
std::unique_lock<std::mutex> lck(mtx);
while (!ready) cv.wait(lck);
// ...
std::cout << "thread " << id << '\n';
}
void go() {
std::unique_lock<std::mutex> lck(mtx);
ready = true;
cv.notify_all();
}
int main ()
{
std::thread threads[10];
// spawn 10 threads:
for (int i=0; i<10; ++i)
threads[i] = std::thread(print_id,i);
std::cout << "10 threads ready to race...\n";
go(); // go!
for (auto& th : threads) th.join();
return 0;
}
If, as I understand, std::condition_variable::wait() blocks the current thread, and that thread is waiting in the point of suspending until some another thread is calling a notify..() function
Why is it necessary to use while() with std::condition_variable::wait()
wait may return whether ready is true or not. If we want to proceed only when ready is true, then we must check it, and continue waiting in case it isn't. A loop is a convenient control structure for repeating an operation until a condition is satisfied.
why wait() may return seemingly spuriously
Because the standard says that it may:
Effects:
Atomically calls lock.unlock() and blocks on *this.
When unblocked, calls lock.lock( (possibly blocking on the lock), then returns.
The function will unblock when signaled by a call to notify_one() or a call to notify_all(), or spuriously.
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.
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.
Here's an sample code on a C++ reference website
#include <chrono>
#include <condition_variable>
#include <iostream>
#include <mutex>
#include <thread>
std::mutex mtx;
std::condition_variable cv;
bool ready = false;
void print_id(int id) {
std::unique_lock<std::mutex> lck(mtx);
while (!ready) {
lck.unlock(); // by curiosity I unlock the lck
cv.wait(lck);
}
std::cout << "thread " << id << '\n';
}
void go() {
std::unique_lock<std::mutex> lck(mtx);
ready = true;
lck.unlock();
cv.notify_all();
}
int main() {
std::thread threads[10];
for (int i = 0; i < 10; ++i)
threads[i] = std::thread(print_id, i);
go();
for (auto &th : threads)
th.join();
return 0;
}
If I don't unlock the unique_lock before calling wait(), everything works normally. Like:
thread 9
thread 1
thread 2
thread 3
thread 4
thread 5
thread 6
thread 7
thread 8
thread 0
I've been told that
At the moment of blocking the thread, the function(wait()) automatically calls lck.unlock(), allowing other locked threads to continue.
So I wonder what if I unlock unique_lock before wait() is called.After I did that, the program behaved weirdly, only one or two threads complete their job(print the "thread X" message), other threads seem to be blocked (by the unique_lock?) forever.
What happened to those unique_locks? Or it's just another undefined behavior of c++ that calling unlock() before wait()?
Thanks!
As stated in documentation of std::condition_variable::wait()
Calling this function if lock.mutex() is not locked by the current thread is undefined behavior.
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));
}