C ++ 0x thread interruption

According to the final C ++ 0x project, there is no way to request thread completion. In this case, if necessary, we need to implement a home-made solution.

On the other hand, boost :: thread provides a mechanism for interrupting a thread in safe mode.

In your opinion, what is the best solution? Developing your own cooperative interruption mechanism or moving to your homeland?

+51
c ++ multithreading c ++ 11
May 7, '10 at 17:17
source share
8 answers

All language specifications say that support is not built into the language. boost::thread::interrupt also needs some support for the thread function:

When an interrupted thread then executes one of the specified breakpoints (or if it is currently blocked at run time)

i.e. when the flow function does not allow the caller to interrupt, you are still stuck.

I'm not sure what you mean with "going native" - โ€‹โ€‹there is no built-in support unless you conjure boost:threads .

However, I would use an explicit mechanism. You should think that you have enough breakpoints, why not make them explicit? Extra code is usually limited in my experience, although you may need to change some expectations from one object to several objects, which, depending on your library, may look uglier.




You can also pull out "do not use exceptions for the control flow", but compared to thread clutter this is just a guide.

+15
May 09 '10 at 12:22
source share

Using the built-in descriptor to cancel the stream is a bad option in C ++, since you need to destroy all objects allocated by the stack. This was the main reason they did not include the cancel operation.

Boost.Thread provides an interrupt mechanism that should be combined into any waiting primitive. Since this can be costly as a general mechanism, the standard did not include it.

You will need to implement it yourself. See my answer here to a similar question on how to implement this yourself. To complete the decision, the interrupt must be executed during the interrupt, and the thread must catch this interrupt and complete.

+10
May 16 '10 at 11:25
source share

It is not safe to stop the stream, because at the moment you are not monitoring the state of any data structures.

If you want to interrupt the current thread, you must implement your own mechanism. IMHO, if you need it, your project is not ready for multiple threads.

If you just want to wait until the stream ends, use join () or the future.

+7
May 07 '10 at 17:28
source share

Implementing your own solution makes the most sense, and it really should not be that difficult. You will need a shared variable that you read / write synchronously, indicating whether the stream is requested to complete, and your stream periodically reads this variable when it is in a state where it can be safely interrupted. When you want to interrupt a stream, you simply write synchronously with this variable, and then join the stream. Assuming that it is interacting properly, he should notice that the variable has been written and turned off, as a result of which the join function is no longer blocked.

If you were family, you would not have won anything; you would simply throw away all the benefits of the standard and cross-platform OOP slicing mechanism. For your code to be correct, the thread would need to collapse together, which implies the connection described above.

+5
May 13 '10 at 9:20
source share

It is unsafe to interrupt the flow, since the state of the whole process becomes uncertain after this point. A thread could receive a critical section before terminating it. This critical section will never be released. The heap can be permanently blocked, etc.

The solution boost::thread::interrupt works by asking nicely. It will interrupt the thread doing something intermittent, for example, waiting for the Boost.Thread condition variable or if the thread performs one of these actions after the interrupt is called. Even then, the thread is not unceremoniously transferred through the meat grinder, because, say, the Win32 TerminateThread function, it simply raises an exception, which, if you were a well-established encoder and used RAII everywhere, would clear it after itself and gracefully exit the stream.

+5
May 15 '10 at 11:32 a.m.
source share

Here is my humble implementation of a thread handler (for C ++ 0x). Hope this will be helpful.

 // Class cancellation_point #include <mutex> #include <condition_variable> struct cancelled_error {}; class cancellation_point { public: cancellation_point(): stop_(false) {} void cancel() { std::unique_lock<std::mutex> lock(mutex_); stop_ = true; cond_.notify_all(); } template <typename P> void wait(const P& period) { std::unique_lock<std::mutex> lock(mutex_); if (stop_ || cond_.wait_for(lock, period) == std::cv_status::no_timeout) { stop_ = false; throw cancelled_error(); } } private: bool stop_; std::mutex mutex_; std::condition_variable cond_; }; // Usage example #include <thread> #include <iostream> class ThreadExample { public: void start() { thread_ = std::unique_ptr<std::thread>( new std::thread(std::bind(&ThreadExample::run, this))); } void stop() { cpoint_.cancel(); thread_->join(); } private: void run() { std::cout << "thread started\n"; try { while (true) { cpoint_.wait(std::chrono::seconds(1)); } } catch (const cancelled_error&) { std::cout << "thread cancelled\n"; } } std::unique_ptr<std::thread> thread_; cancellation_point cpoint_; }; int main() { ThreadExample ex; ex.start(); ex.stop(); return 0; } 
+5
Aug 18 '11 at 10:13
source share

My thread implementation uses the pimpl idiom, and in the Impl class, I have one version for each supported OS, as well as one that uses boost, so I can decide which one to use when creating the project.

I decided to make two classes: one is Thread, which has only the basic services provided by the OS; and the other is SafeThread, which inherits from Thread and has a shared interrupt method.

Thread has a terminate () method that performs intrusive termination. This is a virtual method that is overloaded in SafeThread, where it signals an event object. There is a (static) yeld () method, which from time to time should call the current thread; this method checks whether the event object is signaled, and, if so, throws an exception caught on the calling side of the stream entry point, thereby terminating the stream. When he does this, he signals the second event object, so the calling terminate () object may know that the thread has been safely stopped.

In cases where there is a danger of deadlocks, SafeThread :: terminate () can take a timeout parameter. If the timeout expires, it calls Thread :: terminate (), thereby killing the thread intrusively. This is the last resource when you have something that you cannot control (for example, a third-party API) or in situations where a dead end does more damage than resource leaks, etc.

I hope this will be useful for your decision and will give you a fairly clear idea of โ€‹โ€‹my design options. If not, I can post code snippets to clarify if you want to.

+4
May 16 '10 at 23:51
source share

I agree with this decision. For example, .NET allows you to interrupt any workflow, and I never use this feature and do not recommend it to any professional programmer. I want to decide when a workflow can be interrupted, and what is the way to do this. It differs from hardware, I / O, interface, and other threads. If a thread can be stopped anywhere, it can cause undefined behavior when managing resources, transactions, etc.

+2
May 7, '10 at 17:31
source share



All Articles