C++0X Thread Interruption

How to interrupt a waiting C++0x thread?

Unfortunately I don't see another way than polling, instead of using wait use a timed wait and a variable to state the interruption has been done.

void th(Interruptor& interruptor) {
try {

...

while (cnd1.timed_wait(d)==false) {
interruptor.check_interruption_point();
}
...
} catch (interrupted_exception &) {}
}

The Interruptor class will maintain a boolean variable protected with a mutex or using atomic operations if you have them and two functions interrupt and check_interruption_point, which with throw a interrupted_exception if the boolean is true. The Mater thread will create an Interruptor variable that will be given to the concerned threads at creation time. The master has the the possibility to interrupt at once all the threads that depends on this interruptor. You can of course create an interruptor for each thread if you want to explicitly interrupt one thread at a time.

Up to you to define the duration on the timed wait, so your threads are able to react as soon as your program require.

How might I implement Java like interrupted exception behaviour in C++11

Short answer: you can't; the only way you can do this is to perform your wait asynchronously.

Longer answer:
Conceptually, if a thread could force exceptions to be thrown as an interrupt in other threads, they could do this at any time; not just during your wait or join or io.

It is not always safe to throw an exception - for example in a destructor - since if the stack is already being unwound because of an exception, trying to throw another exception will result in trying to handle 2 exceptions at once - which causes problems. This is true in Java so shouldn't be an unfamiliar concept.

Java and C# are not C++; their thread object does not represent by requirement a native thread; as such everything they do is likely already asynchronous under the hood to prevent thread starvation in the cases where the number of threads allowed is less than the number of thread objects.

This difference is very notable in the thread::abort style methods; which are fine in C# and Java, but very dangerous in C++ since it terminates the thread immediately in C++ whatever it is doing, including being in the middle of new() which may be locking a mutex - causing all further calls to new() in your application to deadlock.

How to terminate a std::thread?

Don't detach the thread. Instead, you can have a data member that hold a pointer to the thread, and join the thread in destructor.

class YourClass {
public:
~YourClass() {
if (_thread != nullptr) {
_thread->join();
delete _thread;
}
}
void mainProcees() {
_thread = new thread(&YourClass::downloadImg,this);
}
private:
thread *_thread = nullptr;
};

UPDATE

Just as @milleniumbug pointed out, you don't need dynamic allocation for the thread object, since it is movable. So the other solution is as follows.

class YourClass {
public:
~YourClass() {
if (_thread.joinable())
_thread.join();
}
void mainProcess() {
_thread = std::thread(&YourClass::downloadImg, this);
}
private:
std::thread _thread;
};

How do I terminate a thread in C++11?

  1. You could call std::terminate() from any thread and the thread you're referring to will forcefully end.

  2. You could arrange for ~thread() to be executed on the object of the target thread, without a intervening join() nor detach() on that object. This will have the same effect as option 1.

  3. You could design an exception which has a destructor which throws an exception. And then arrange for the target thread to throw this exception when it is to be forcefully terminated. The tricky part on this one is getting the target thread to throw this exception.

Options 1 and 2 don't leak intra-process resources, but they terminate every thread.

Option 3 will probably leak resources, but is partially cooperative in that the target thread has to agree to throw the exception.

There is no portable way in C++11 (that I'm aware of) to non-cooperatively kill a single thread in a multi-thread program (i.e. without killing all threads). There was no motivation to design such a feature.

A std::thread may have this member function:

native_handle_type native_handle();

You might be able to use this to call an OS-dependent function to do what you want. For example on Apple's OS's, this function exists and native_handle_type is a pthread_t. If you are successful, you are likely to leak resources.

It's legal to mix c++0x threads with gio GCancellable?

I am not very familiar with GCancellable. After a quick read through, it appears to be a hierarchical notification system.

If that is the case then yes you can easily mix GCancellable with std::thread.


There is no easy way to make a std::thread cancellable.

This is wrong.

There is no non-zero cost way to make all std::threads cancellable.

This is correct.

The problem is providing a general solution. Notification is easy enough. The hard part is making sure the thread sees the notification. The thread may be blocked on a mutex or IO. You cannot just kill the thread. All sorts of bad can occur.

Each individual implementation is free to implement their own cancellation system tailored to you particular needs.

If you need to be interruptable from a blocking mutex, make sure you only use timed_mutexes, and that you call g_cancellable_is_cancelled frequently enough that your thread will cancel as needed.

Gracefully stopping an std::thread?

.. well it depends. What is the thread doing? Does it block on anything, I/O, sleep, or some other API?

If it's just CPU-looping all the time and it does not matter about exactly when it stops and it stops and exits, then just use a boolean. There's no point, in this case, in locking up a 'stopAndExit' boolean.

If the work thread does not read it as true on one loop when perhaps it should, because of some lack of atomicity, it will get it next time round. Why perform locks/API calls when you don't have to? A kernel level call from user to acquire/release a synchronisation object will take ages compared with a simple 'if (stop) exit;', wasting time on each loop that could have been used for calculation, or whatever you do in your CPU-bound thread.

It is cross-platform

Regards,
Martin



Related Topics



Leave a reply



Submit