Thread Interruption in Boost Thread Library
2014-08-11 15:45
288 查看
One of the new features introduced in the upcoming 1.35.0 release of the
boost thread library is support for interruption of a running thread. Similar to the Java and .NET interruption support, this allows for one thread to request another thread to stop at the nextinterruption point. This is the only way to
explicitly request a thread to terminate that is directly supported by the Boost Thread library, though users can manually implement cooperative interruption if required.
Interrupting a thread in this way is much less dangerous than brute-force tactics such as
locks, this can also potentially lead to deadlock when another thread tries to acquire those locks at some future point. Interruption is also easier and more reliable than rolling your own cooperative termination scheme using mutexes, flags, condition variables,
or some other synchronization mechanism, since it is part of the library.
then it cannot be interrupted.
Calling
points, and it might be that a thread never executes an interruption point, so never sees the request. Currently, the interruption points are:
[cpp]
view plaincopy
boost::thread::join()
boost::thread::timed_join()
boost::condition_variable::wait()
boost::condition_variable::timed_wait()
boost::condition_variable_any::wait()
boost::condition_variable_any::timed_wait()
boost::this_thread::sleep()
boost::this_thread::interruption_point()
When a thread reaches one of these interruption points, if interruption is enabled for that thread then it checks its interruption flag. If the flag is set, then it is cleared, and a
is already blocked on a call to one of the interruption points with interruption enabled when
acceptable to interrupt it again. This can be used, for example, when a worker thread that is processing a series of independent tasks — if the current task is interrupted, the worker can handle the interruption and discard the task, and move onto the next
task, which can then in turn be interrupted. It also allows the thread to catch the exception and terminate itself by other means, such as returning error codes, or translating the exception to pass through module boundaries.
Objects of this class disable interruption for the thread that created them on construction, and restore the interruption state to whatever it was before on destruction:
[cpp]
view plaincopy
void f()
{
// interruption enabled here
{
boost::this_thread::disable_interruption di;
// interruption disabled
{
boost::this_thread::disable_interruption di2;
// interruption still disabled
} // di2 destroyed, interruption state restored
// interruption still disabled
} // di destroyed, interruption state restored
// interruption now enabled
}
effects of an instance of
object in question. This will restore the interruption state to what it was when the
object is destroyed:
[cpp]
view plaincopy
void g()
{
// interruption enabled here
{
boost::this_thread::disable_interruption di;
// interruption disabled
{
boost::this_thread::restore_interruption ri(di);
// interruption now enabled
} // ri destroyed, interruption disabled again
{
boost::this_thread::disable_interruption di2;
// interruption disabled
{
boost::this_thread::restore_interruption ri2(di2);
// interruption still disabled
// as it was disabled when di2 constructed
} // ri2 destroyed, interruption still disabled
} //di2 destroyed, interruption still disabled
} // di destroyed, interruption state restored
// interruption now enabled
}
restored when the scope is exited (whether normally, or by an exception), and that you cannot enable interruptions in the middle of an interruption-disabled block unless you're in full control of the code, and have access to the
instance.
At any point, the interruption state for the current thread can be queried by calling
does nothing except check for an interruption, and can therefore be used in long-running code that doesn't execute any other interruption points, in order to allow for cooperative interruption. Just like the other interruption points,
respects the interruption enabled state, and does nothing if interruption is disabled for the current thread.
been acknowledged the thread is effectively dead.
you need to use
for an exception to propagate into a C stack frame.
For portable code, I recommend interruption over cancellation. It's supported on all platforms that can use the Boost Thread library, and it works well with C++ code — it's just another exception, so all your destructors and catch blocks work just fine.
Posted by Anthony Williams
From:http://www.justsoftwaresolutions.co.uk/threading/thread-interruption-in-boost-thread-library.html
boost thread library is support for interruption of a running thread. Similar to the Java and .NET interruption support, this allows for one thread to request another thread to stop at the nextinterruption point. This is the only way to
explicitly request a thread to terminate that is directly supported by the Boost Thread library, though users can manually implement cooperative interruption if required.
Interrupting a thread in this way is much less dangerous than brute-force tactics such as
TerminateThread(), as such tactics can leave broken invariants and leak resources. If a thread is killed using a brute-force method and it was holding any
locks, this can also potentially lead to deadlock when another thread tries to acquire those locks at some future point. Interruption is also easier and more reliable than rolling your own cooperative termination scheme using mutexes, flags, condition variables,
or some other synchronization mechanism, since it is part of the library.
Interrupting a Thread
A running thread can be interrupted by calling theinterrupt()member function on the corresponding
boost::threadobject. If the thread doesn't have a
boost::threadobject (e.g the initial thread of the application),
then it cannot be interrupted.
Calling
interrupt()just sets a flag in the thread management structure for that thread and returns: it doesn't wait for the thread to actually be interrupted. This is important, because a thread can only be interrupted at one of the predefinedinterruption
points, and it might be that a thread never executes an interruption point, so never sees the request. Currently, the interruption points are:
[cpp]
view plaincopy
boost::thread::join()
boost::thread::timed_join()
boost::condition_variable::wait()
boost::condition_variable::timed_wait()
boost::condition_variable_any::wait()
boost::condition_variable_any::timed_wait()
boost::this_thread::sleep()
boost::this_thread::interruption_point()
When a thread reaches one of these interruption points, if interruption is enabled for that thread then it checks its interruption flag. If the flag is set, then it is cleared, and a
boost::thread_interruptedexception is thrown. If the thread
is already blocked on a call to one of the interruption points with interruption enabled when
interrupt()is called, then the thread will wake in order to throw the
boost::thread_interruptedexception.
Catching an Interruption
boost::thread_interruptedis just a normal exception, so it can be caught, just like any other exception. This is why the "interrupted" flag is cleared when the exception is thrown — if a thread catches and handles the interruption, it is perfectly
acceptable to interrupt it again. This can be used, for example, when a worker thread that is processing a series of independent tasks — if the current task is interrupted, the worker can handle the interruption and discard the task, and move onto the next
task, which can then in turn be interrupted. It also allows the thread to catch the exception and terminate itself by other means, such as returning error codes, or translating the exception to pass through module boundaries.
Disabling Interruptions
Sometimes it is necessary to avoid being interrupted for a particular section of code, such as in a destructor where an exception has the potential to cause immediate process termination. This is done by constructing an instance ofboost::this_thread::disable_interruption.
Objects of this class disable interruption for the thread that created them on construction, and restore the interruption state to whatever it was before on destruction:
[cpp]
view plaincopy
void f()
{
// interruption enabled here
{
boost::this_thread::disable_interruption di;
// interruption disabled
{
boost::this_thread::disable_interruption di2;
// interruption still disabled
} // di2 destroyed, interruption state restored
// interruption still disabled
} // di destroyed, interruption state restored
// interruption now enabled
}
effects of an instance of
boost::this_thread::disable_interruptioncan be temporarily reversed by constructing an instance of
boost::this_thread::restore_interruption, passing in the
boost::this_thread::disable_interruption
object in question. This will restore the interruption state to what it was when the
boost::this_thread::disable_interruptionobject was constructed, and then disable interruption again when the
boost::this_thread::restore_interruption
object is destroyed:
[cpp]
view plaincopy
void g()
{
// interruption enabled here
{
boost::this_thread::disable_interruption di;
// interruption disabled
{
boost::this_thread::restore_interruption ri(di);
// interruption now enabled
} // ri destroyed, interruption disabled again
{
boost::this_thread::disable_interruption di2;
// interruption disabled
{
boost::this_thread::restore_interruption ri2(di2);
// interruption still disabled
// as it was disabled when di2 constructed
} // ri2 destroyed, interruption still disabled
} //di2 destroyed, interruption still disabled
} // di destroyed, interruption state restored
// interruption now enabled
}
boost::this_thread::disable_interruptionand
boost::this_thread::restore_interruptioncannot be moved or copied, and they are the only way of enabling and disabling interruption. This ensures that the interruption state is correctly
restored when the scope is exited (whether normally, or by an exception), and that you cannot enable interruptions in the middle of an interruption-disabled block unless you're in full control of the code, and have access to the
boost::this_thread::disable_interruption
instance.
At any point, the interruption state for the current thread can be queried by calling
boost::this_thread::interruption_enabled().
Cooperative Interruption
As well as the interruption points on blocking operations such assleep()and
join(), there is one interruption point explicitly designed to allow interruption at a user-designated point in the code.
boost::this_thread::interruption_point()
does nothing except check for an interruption, and can therefore be used in long-running code that doesn't execute any other interruption points, in order to allow for cooperative interruption. Just like the other interruption points,
interruption_point()
respects the interruption enabled state, and does nothing if interruption is disabled for the current thread.
Interruption is Not Cancellation
On POSIX platforms, threads can be cancelled rather than killed, by callingpthread_cancel(). This is similar to interruption, but is a separate mechanism, with different behaviour. In particular, cancellation cannot be stopped once it is started: whereas interruption just throws an exception, once a cancellation request has
been acknowledged the thread is effectively dead.
pthread_cancel()does not always execute destructors either (though it does on some platforms), as it is primarily a C interface — if you want to clean up your resources when a thread is cancelled,
you need to use
pthread_cleanup_push()to register a cleanup handler. The advantage here is that
pthread_cleanup_push()works in C stack frames, whereas exceptions don't play nicely in C: on some platforms it will crash your program
for an exception to propagate into a C stack frame.
For portable code, I recommend interruption over cancellation. It's supported on all platforms that can use the Boost Thread library, and it works well with C++ code — it's just another exception, so all your destructors and catch blocks work just fine.
Posted by Anthony Williams
From:http://www.justsoftwaresolutions.co.uk/threading/thread-interruption-in-boost-thread-library.html
相关文章推荐
- Thread Interruption in Boost Thread Library
- Break the infinity thread loop using boost::this_thread::interruption_point()
- rpmdb: Thread/process 9180/139855524558592 failed: Thread died in Berkeley DB library
- BOOST ThreadPool 编译错误"TIME_UTC was not declared in this scope"
- Linux rpm 报错Thread died in Berkeley DB library
- Exception in thread "main" java.lang.UnsatisfiedLinkError: no ocijdbc11 in java.library.path
- Exception in thread "main" java.lang.UnsatisfiedLinkError: Unable to load library
- An Introduction to Thread in the upcoming book From: Introduction to the C++ Boost Libraries
- Nginx线程池性能提升9倍(Thread Pools in NGINX Boost Performance 9x!)
- Exception in thread "main" java.lang.UnsatisfiedLinkError: no jniopencv_highgui in java.library.path
- linux安装mongo c++ driver,出现Checking for C++ library boost_thread-mt... no的解决办法
- rpmdb: Thread/process 10646/3086534416 failed: Thread died in Berkeley DB library
- rpmdb: Thread/process 10646/3086534416 failed: Thread died in Berkeley DB library
- Exception in thread "main" java.lang.UnsatisfiedLinkError: no hello in java.library.path
- Thread Safety in the Standard C++ Library
- BOOST ThreadPool 编译错误"TIME_UTC was not declared in this scope"
- Thread Safety in the Standard C++ Library(From MSDN)
- [C++0x] Boost Thread in Vector and use lamda as thread function
- Thread Pools in NGINX Boost Performance 9x!
- Starting elasticsearch: Exception in thread "main" java.lang.IllegalStateException: Could not load p