How can I interrupt a sleeping/blocked boost::thread?
I am using Boost v1.33.1, upgrading is not an option.
Thank you.
How can I interrupt a sleeping/blocked boost::thread?
I am using Boost v1.33.1, upgrading is not an option.
Thank you.
There is no way to interrupt blocked thread in boost::thread. You need to implement proper thread interruption yourself, using boost::conditional for example.
AFAIK Any existing ways to interrupt running thread (TerminateThread in Windows API for example) only lead to problems (memory leaks one of them).
A quick perusal of the documentation for boost.thread in 1.33 suggests that there is no portable way to achieve interruption. Thread interruption was introduced (for threads in one of the boost "interruption points") in 1.35.
As a result the only option I can think of is to use signals (which aren't in 1.33 either, so you'll need to fall back on, for example, pthreads) combined with time-outs on any methods that are blocking. Basically use signals to wake threads that are asleep by having them sleep waiting for the signal and timeouts on blocking threads to have them wake up and check to see if they should exit. Unfortunately this is a highly undesirable solution, and to some extent amounts to what newer versions of boost do internally anyway.
If you're using boost.thread, then you should consider upgrading to a more recent version for other projects because 1.33 doesn't support the vast majority of constructs that are essential for multi-threading.
I agree with begray, look into condition variables. If you have threads you want to wake up from time to time, they are what boost expects you to use. If you expect that threads are going to block on other calls (like calls into BSD sockets or something similar) this doesn't help you. You will need to use the timeout facilities of those calls directly, if they exist.
Here's an example, using only facilities available in boost 1.33.1. I haven't compiled it, so there may be small errors. I've included the use of a nebulous Work class, but you don't need to work with shared data at all to use this pattern. Only the mutex and the condition variable are needed.
Work work;
boost::condition workAvailable;
boost::mutex workMutex;
void Producer()
{
{
boost::mutex::scoped_lock lock(workMutex);
UpdateWork(work);
workAvailable.notify_one();
}
boost::mutex::scoped_lock lock(workMutex);
work.SetOver();
workAvailable.notify_one();
}
void Consumer()
{
//This thread uses data protected by the work mutex
boost::mutex::scoped_lock lock(workMutex);
while(true)
{
//this call releases the work mutex
//when this thread is notified, the mutex is re-acquired
workAvailable.wait(lock);
//once we have the mutex we can work with shared data
//which might require this thread to terminate
if(work.Over())
{
return;
}
DoWork(work);
}
}
The producer thread will create one unit of work, and then block. The consumer thread will do the work, and then block. Then the producer thread will set the termination condition and exit. The consumer will then exit.