Passing data from caller thread to the method in another boost::thread - c++

I have rather a noob question regarding concurrency in C++ (Using Boost threads) on which I haven't found a clear answer.I have a worker class which runs in a separate thread.I init the worker on the start of the program only once.This worker is "lazy" and does some data encoding only when it receives it from the calling thread.In the worker I have a public method:
void PushFrame(byte* data);
which pushes the data to the std::stack member variable so the worker can access it each time new data object is pushed there.
What I don't understand is how such an interaction generally done? Can I just call PushFrame() from the caller thread and pass the argument? Or do I have to access the methods in the worker in some special way?

Usually you use a producer-consumer-queue for this type of work.
Whenever the worker thread runs out of work he wait()s on a boost::condition_variable which is protected by the same boost::mutex as the stack holding the data for the worker thread (you might want to use a queue here instead to minimize the risk of unfair work scheduling).
Your PushFrame() function now calls notify_one() on that condition variable whenever it inserts new data into the stack. That way, the worker thread will truly sleep (i.e. the OS scheduler will probably not give it any timeslice) until there is actually work to be done.
The easiest thing to get wrong here is the locking of the mutex protecting both the stack and the condition_variable. Besides avoiding races on the data structures, you also need to take care that the condition_variable does not miss a notify call and therefore might get stuck waiting while there actually is more work available.
class Worker {
void PushFrame(byte* data)
{
boost::lock_guard<boost::mutex> lk(m_mutex);
// push the data
// ...
m_data_cond.notify_one();
}
void DoWork()
{
while(!done) {
boost::unique_lock<boost::mutex> lk(m_mutex);
// we need a loop here as wait() may return spuriously
while(is_out_of_work()) {
// wait() will release the mutex and suspend the thread
m_data_cond.wait(lk);
// upon returning from wait() the mutex will be locked again
}
// do work from the queue
// ...
}
}
boost::mutex m_mutex;
boost::condition_variable m_data_cond;
[...]
};

Related

Can a single thread double-lock a mutex?

If I want a thread to pause for a while, until certain conditions are met, can I double-lock the mutex?
Here's a basic example of the idea I'm working with right now:
class foo
{
public:
static std::mutex processingMutex;
void infinite_processing_loop()
{
processingMutex.lock(); // Lock the mutex, initially
while(true)
{
if ( /*ready for this thread to process data*/ )
{
// ... perform one round of data processing ...
}
else // NOT ready for this thread to process data
{
/* Pause this thread,
and wait for another thread to unlock this mutex
(when more data might be ready for processing) */
processingMutex.lock();
}
}
processingMutex.unlock(); // Will never be executed
}
};
Will the processing thread halt, when it tries to double-lock the mutex?
And can another thread unlock the same mutex, causing the halted processing thread to resume?
Or does std::mutex automatically recognize when mutex is locked twice from the same processing thread?
std::mutex will usually deadlock on second attempt to lock by the owner thread. And even if it didn't, it's considered a bug for an application to attempt with this primitive.
std::recursive_mutex will allow re-entrant locks. So if you lock twice, you need to unlock twice before the mutex is available for other threads to grab.
There's a school of thought that any design that involves recursively acquiring a mutex after it's already been locked is a design flaw. I'll try to dig up that thread and add it.

std::condition_variable wait() and notify_one() synchronization

Preface: I've seen similar questions here, but not one of them seems to answer my question.
Is there a reliable way to make sure that wait() method in consumer thread is called before the first notify_one() call from the producer thread?
Even with unique_lock in the consumer thread, there is a possibility that the producer thread will run first, lock the mutex and call notify() before the consumer calls wait(), therefore, my app will be missing first notify() call.
EDIT: Thanks for all your answers, they did help me. My problem was with first wait-notify() within this consumer loop:
while (!timeToQuit) {
gdcv.wait(gdcondlock);
gdlock.lock();
//spurious wakeup
if (gdQueue.empty()) {
gdlock.unlock();
continue;
}
//some work here
gdlock.unlock();
}
I guess I'll have to write extra code for the first loop iteration.
EDIT2: This loop and second lock(unique_lock btw) are there because there are multiple producers and consumers accessing queue.
EDIT3: The correct way for waiting on this particular thread with the help of boost::lockfree::queue, in case anyone has similar problem:
nfq_data* data;
while (!timeToQuit) {
gdcv.wait(gdlock,[&]{return !gdQueue.empty() || timeToQuit;});
gdQueue.pop(data);
gdlock.unlock();
}
Even with unique_lock in consumer thread there is a possibility that producer thread will run first, lock the mutex and call noify() before consumer calls wait(), therefore, my app will be missing first nofity() call.
Either the consumer has something to wait for, or it doesn't. If it has something to wait for, there is no problem. If it doesn't have anything to wait for, don't call wait. It really is that simple.
Call wait if, and only if, you want to wait.
Condition variables exist to solve the problem of how you can release a lock and wait without taking the risk that you will wait for something that has already happened. They solve it by providing a function that atomically releases the lock and waits. They cannot miss a wakeup because they hold the lock when they decide to sleep.
It sounds like you are trying to (mis)use condition_variable to implement a "barrier".
A condition variable allows you to wait for some condition to become true, tested via some predicate, e.g. "there is work available", and you should always test the predicate before waiting, which ensures you don't "miss" the event and wait when you should be working.
Using a condition variable purely to wait, without an associated predicate, does not work well. That's not how they are designed to be used.
If you are trying to make all threads wait at a particular point in the code and only proceed when they have all arrived then you are using a slightly different concept, known as a barrier.
The C++ Concurrency TS defines barriers (and the slightly simpler concept of "latches") for the C++ Standard Library, see the draft N4538.
You can define a barrier yourself by defining a class with a counter, which uses a condition_variable internally. The condition it needs to wait on is "all N threads have incremented the counter". Then you can make the producer and all consumers wait at the barrier, and they will all block until the last thread reaches the barrier. Even if the producer reaches the barrier and starts waiting first, you are guaranteed that the consumers will also stop and wait at the barrier, until all threads reach it, then they will all proceed.
No, it's up to you to take care of threads synchronization.
If you don't want to miss a notify call even if it happens before the the consumer starts waiting, you must control this eventuality, recording somewhere that the producer is done, and then not call the wait() function at all.
For example, you can implement a sort of event class, that wait on the condition variable only if the event has not happened yet:
#include <mutex>
#include <condition_variable>
class Event
{
public:
Event();
void set_event();
void reset_event();
void wait_event();
private:
std::mutex mtx;
std::condition_variable cv;
bool is_set;
};
Event::Event()
: is_set{false}
{}
void Event::set_event()
{
std::lock_guard<std::mutex> lck{mtx};
is_set = true;
cv.notify_all();
}
void Event::reset_event()
{
std::lock_guard<std::mutex> lck{mtx};
is_set = false;
}
void Event::wait_event()
{
std::unique_lock<std::mutex> lck{mtx};
if( is_set )
return;
cv.wait(lck, [this]{ return is_set;} );
}
Even with unique_lock in consumer thread there is a possibility that producer thread will run first, lock the mutex and call noify() before consumer calls wait(), therefore, my app will be missing first nofity() call
If the producer has already run, then the consumer doesn't have to wait and therefore shouldn't call wait. If the consumer only waits when it needs to - and the condition is snychronized - then it cannot miss a notify that it needs to notice.

Make threads call init once every cycle

I have a code that looks like the following, with many threads doing this code snippet:
if (!shouldWork)
{
long timeToSleep = 0;
if (FindTimeToSleep(timeToSleep)) {
Sleep(timeToSleep);
InnerInitialize();
}
}
}
Now, The function InnerInitialize should be called only once after the sleep timeout. There are many threads that can sleep, after they wake up, only one thread should call InnerInitialize. We could use a simple semaphore, but the problem is that in the next cycle, after all the threads have passed the call to InnerInitialize, if the threads get to sleep again, we may need to call the function again (only once). So this is similar to std::call_once, but only periodically.
How can we achieve this?
You should use a shared mutex for synchronization.
ignoring how each thread gets to the Sleep(timeToSleep) method this is what should happen:
pthread_mutex_t mutex;
int initialized;
.......
Sleep(timeToSleep);
pthread_mutex_lock(&mutex); //critical section
if (!initialized)
{
intialized = 1;
InnerInitialize();
}
pthread_mutex_unlock (&mutex);
You still have to reset the intialized variable somewhere in the code but I don't fully understand it to help you with that.
This of course assumes that all threads go to sleep for the same amount of time and that period is long enough to guarantee that no thread goes to sleep(again) before all the others have woken up.
Try using a single thread which manages the rest. Your, what seems to be per thread group, initialization and sleep between sessions would be managed from that one thread whilst the worker threads in the group would do their stuff when needed, possibly via a job queue.
This also cleanly separates out the responsibilities of each threads job.
Synchronize each thread around a "generational counter," which is simply an incrementing counter that signal its changes (via mutex and condition variable).
When the counter increments, it is a "new workday," if you will, and the workers know to begin again. A separate, dedicated scheduling thread performs the increment and initialization routines, and it does not need to know how many workers there are.
In pseudocode:
// main / global init
workCycle = new GenerationalCounter() // initialized to _generation 0
// worker thread
myCurrentCycle = 0
while true:
myCurrentCycle = workCycle.awaitNewGeneration(myCurrentCycle)
// lock mutex
// cond_wait until _generation != myCurrentCycle
// fetch _generation for return
// unlock mutex
DoWork()
// scheduler thread
while true:
SleepUntilNextWorkCycle()
InnerIntializer()
workCycle.increment() // lock mutex
// increment _generation
// broadcast
// unlock mutex
With a little bookkeeping, InnerInitialize() could be moved out of the scheduling thread and into one of the workers by extending GenerationalCounter to run a callback in the very first thread released after a generation increment.

Event queue using boost::asio and strands: Waiting for new events

So I want to make a synchronous event queue in c++ on a custom thread. As far as I can tell, boost::asio::strand is an excelent candidate for this, with one twist: when asio::run() is called, it only runs while there are events in the strand's queue. The code:
this->control_strand_.reset(new boost::asio::strand(control_io_service_));
control_thread_ = boost::thread(boost::bind(&boost::asio::io_service::run,&control_io_service_));
control_thread_.join();
Returns immediately. Now I could go with the answer of Boost Asio - How to know when the handler queue is empty?, but this has a while-loop-wait in it. I'd rather have it be more event based (aka, wait for a "wrap" call in the while look when the queue is empty). Th only way I can think to do this is completely wrap the strand class, having it trigger a signal whenever "wrap" is called (something like, pseudo code)
//some member variables
boost::condition_variable cond_var;
boost::mutex mut;
std::unique_ptr<boost::asio::strand> control_strand_;
boost::asio::io_service control_io_service_
//while loop,running on event processing thread
void MessageProcessor()
{
while (true)
{
{
boost::unique_lock<boost::mutex> lock(mut);
cond_var.wait(lock);
}
control_io_service_.run();
}
}
//post call,from different thread
template <typename Handler>
void wrap(Handler hand)
{
cond_var.notify_all();
control_strand_->wrap(hand);
}
This will run the queue forever without the while loop (my synchronization is a little off, but thats not an issue atm). Is there a better, more standard, way?
You can use io_service directly, it implements an "implicit strand". To keep it running, just give it io_service::work object, like in the io_service reference (see "Stopping the io_service from running out of work").
Note that io_service is intentionally thread-safe, so you can post() functors to it from external threads.

C++ Gtk threading. Am I doing it right?

I have a gtkmm application and I'm trying to put some long running tasks into separate threads so they don't lock the GUI. Here's a tutorial I've based my design on:
http://www.velvetcache.org/2008/09/30/gtkmmglibmm-thread-example
I use Glib::Dispatcher signals to notify the GUI thread when the work is done or something needs to be updated, however I'm not sure how to pass the data between the worker thread and GUI thread. So far I've been passing a pointer to the class which creates the worker to the worker and then modifying public members of the class, but something tells me it's not the most correct to do it. Here's an example:
class Some_GUI_class
{
public:
std::string thread_message;
private:
Worker_class* worker;
void start_worker()
{
if (worker != NULL) return;
worker = new Worker_class(this);
worker->sig_message.connect(sigc::mem_fun(*this, &Some_GUI_class::display_message_from_thread);
worker.start();
}
void display_message_from_thread()
{
some_label->set_text(thread_message);
}
}
class Worker_class
{
public:
Worker_class(Some_GUI_class* gui_class) : gui_class(gui_class)
{}
void start()
{
thread = Glib::Thread::create(sigc::mem_fun(*this, &Worker_class::run), true);
}
Glib::Dispather sig_message;
protected:
Glib::Thread* thread;
Glib::Mutex mutex;
Some_GUI_class* gui_class;
void run()
{
// ...
gui_class->thread_message = "Message from a thread!";
sig_message();
}
}
This essentialy works, but I guess if the GUI thread wanted to modify thread_message at the same time there would be a problem? Is it safe to do it like this then as long as I'm sure the variables are only modified by a single thread or is there a better way?
You have a race condition. Even if your gui thread doesn't modify thread_message, allowing the GUI thread to read it while another thread is modifying it is not going to give you long term happiness. This is because std::string is not itself protected from multiple threads accessing it, and has multiple internal fields. If one thread is in the process of modifying one of its internal fields, while another is reading them, the internal state will not be consistent from the point of view of the second.
You can use a mutex in the GUI class to protect access to the variables which might be accessed by another thread. Lock and unlock the mutex in get/set routines, and use those routines for all other accesses to ensure that only one thread gets to access or modify the variables at one time.
Generally mutex usage is not enough to achieve the desired behaviour. The same worker thread (or another one if you have it) could want to send another message while first one had not been processed by the main thread yet. That is why in addition to mutex you should use message queue (e.g. object of std::deque<std::string> class) instead of just a std::string Some_GUI_class::thread_message variable to avoid this kind of message loss.