I want to kill a std::thread using its thread object?
Solution 1
@bamboon's answer is good, however I feel this deserves a stronger statement.
Whatever the language you use, your program will acquire and release resources: memory, file descriptors, ... For simple programs that are fired in one shots, leaking resources does not matter much: when the program ends modern OSes automatically take the resources back; however for long-running programs a basic requirement is not to leak resources, or at least not repetitively.
Therefore, you should have been taught from the beginning that when you acquire a resource you will have to ensure it is released at one point:
void foo(int i) {
int* array = malloc(sizeof(int) * i);
/* do something */
free(array);
}
So, ask yourself the question:
- what happens when I kill the program ?
- what happens when I kill the thread ?
Well, as we said, when a program ends the OS gathers the resources back, so assuming (and this is some assumption) that you did not acquire a resource on another system OR that this system is well protected against such abuse, no harm, no foul.
However, when you kill a thread, the program still runs, thus the OS does not gather the resources back. You leaked memory, you locked a file for writing that you cannot unlock any longer, ... You shall not kill threads.
Higher level languages have a way to handle this: exceptions. Because programs should be exception safe anyway, Java (for example) will kill a thread by pausing it, throwing an exception at the point of execution, and gently unwind the stack. However there is no such facility in C++, yet.
Is it impossible ? No, obviously not. Actually, you could perfectly reuse the very same idea:
- encapsulate
std::thread
,interruptible_thread
class will also contain an interrupt flag - pass the address of the flag to
std::thread
when launching it, and store it in a thread-local way - instrument your code with check-points where you check whether the interrupt flag is set or not, and when it is throw an exception
That is:
// Synopsis
class interrupt_thread_exception;
class interruptible_thread;
void check_for_interrupt();
// Interrupt exception
class interrupt_thread_exception: public virtual std::exception {
public:
virtual char const* what() const override { return "interrupt"; }
}; // class interrupt_thread_exception
// Interruptible thread
class interruptible_thread {
public:
friend void check_for_interrupt();
template <typename Function, typename... Args>
interruptible_thread(Function&& fun, Args&&... args):
_thread([](std::atomic_bool& f, Function&& fun, Args&&... args) {
_flag_ref = &f; fun(std::forward<Args>(args)...);
},
_flag,
std::forward<Function>(fun),
std::forward<Args>(args)...)
{}
bool stopping() const { return _flag.load(); }
void stop() { _flag.store(true); }
private:
static thread_local std::atomic_bool* _flag_ref = nullptr;
std::atomic_bool _flag = false;
std::thread _thread;
}; // class interruptible_thread
// Interruption checker
inline void check_for_interrupt() noexcept(false) {
if (not interruptible_thread::_flag_ref) { return; }
if (not interruptible_thread::_flag_ref->load()) { return; }
throw interrupt_thread_exception();
} // check_for_interrupt
Now you can just sprinkle your threaded code with checks for interrupt at appropriate places.
Solution 2
You can't.
std::threads
are not interruptible. You can use boost::thread
which offers this feature.
Boost does this by defining "interrupt points" on which the thread will end if it is interrupted and reaches such a point.
Nevertheless, most of the time thinking about a redesign might be the cleanest and easiest way to reach what you are trying to achieve.
If you are still looking for a C++11 implementation of interruptible threads checkout out Anthony Williams (owner of boost thread) book "C++ Concurrency in Action". He goes through a basic implementation of how such a thing can be achieved.
std::thread::native_handle
gives you access to the platform specific underlying thread handle which might support interrupting, however this approach makes your code unportable and probably not cleaner in any way.
CPS
Updated on September 15, 2020Comments
-
CPS over 3 years
Possible Duplicate:
C++0x thread interruptionI am trying to kill/stop a c++ std::thread by using its thread object.
How can we do this?