This replaces #8023 with a solution that moves us directly to std::thread, rather than using an intermediate wrapper.
Background
std::thread is pretty much a drop-in replacement for boost::thread, except that boost::thread is interruptible. We’ve used those interruptions, but we’ll have to drop them eventually as they didn’t become part of the spec.
When an interruption point is hit, it throws an instance of boost::thread_interrupted. boost::thread catches these automatically by default.
The interruption points are defined as:
0
1 boost::thread::join()
2 boost::thread::timed_join()
3 boost::thread::try_join_for(),
4 boost::thread::try_join_until(),
5 boost::condition_variable::wait()
6 boost::condition_variable::timed_wait()
7 boost::condition_variable::wait_for()
8 boost::condition_variable::wait_until()
9 boost::condition_variable_any::wait()
10 boost::condition_variable_any::timed_wait()
11 boost::condition_variable_any::wait_for()
12 boost::condition_variable_any::wait_until()
13 boost::thread::sleep()
14 boost::this_thread::sleep_for()
15 boost::this_thread::sleep_until()
16 boost::this_thread::interruption_point()
The ones relevant to us are primarily boost::condition_variable_any::wait()
, boost::this_thread::sleep_for()
, and of course boost::this_thread::interruption_point()
Any boost::thread will immediately throw boost::thread_interrupted if those are hit at any point. So we can’t simply s/boost::thread/std::thread/g, as we would never be able to exit.
Changes
- All threads are now externally interruptible. Rather than having a single bool for shutting down, I’ve attempted to notify each relevant subsystem. But because they’re not well-defined, the notifications are somewhat arbitrary as well.
- For long-running threads, our own
thread_interrupted
andinterruption_point
have been added. - Threads should call TraceThread if they may hit an interruption_point.
- MilliSleep is no longer interruptible.
- boost::thread_group is gone. All threads are now managed individually
Future changes
There is lots of cleanup to be done post-merge. I was very tempted to include cleanups here, but I’ve elected to keep the changes minimal. Todo:
- s/boost::mutex/std::mutex/
- s/boost::condition_variable/std::condition_variable/
- s/boost::chrono/std::chrono/
- Drop a ton of boost includes
- Drop other boost cruft (like catching
boost::thread_interrupted
)
Also, I started on this by creating a base class for launching threads. Each instance would be responsible for implementing Interrupt() and Stop(). But because this is already a complex set of changes, I think it’s best to do that as a separate step.