[thread] 2 questions about thread interruption
Hi, I have two questions connected to thread interruption in Boost.Thread. *1.* The docs say that interrupt_and_join_if_joinable is defined as follows: ``` struct interrupt_and_join_if_joinable{ void operator()(thread& t) { t.interrupt(); if (t.joinable()) { t.join(); } }}; ```
2016-04-18 23:42 GMT+02:00 Andrzej Krzemienski
Hi, I have two questions connected to thread interruption in Boost.Thread.
*1.* The docs say that interrupt_and_join_if_joinable is defined as follows:
``` struct interrupt_and_join_if_joinable{
void operator()(thread& t) { t.interrupt(); if (t.joinable()) { t.join(); } }};
```
Sorry, let me continue with the question. Is there a reason why t.interrupt() is called without checking if t is joinable? This looks uncomfortable to me that I would be potentially calling interrupt() on a not-a-thread. *2.* When I make a call to this_thread::wait_for(), blocking for a long time in thread t2, and the instant later I call t2.interrupt() from another thread t1. Do I have to wait the long time until wait_for() stops blocking t2, or does thread_interrupted get called 'immediately' after interrupt() is called from t1? *3.* Does the support for interruption points require the other synchronization operations (like locks on mutexes) to be slower (in order to monitor interruption requests)? Regards, &rzej
Le 18/04/2016 23:50, Andrzej Krzemienski a écrit :
2016-04-18 23:42 GMT+02:00 Andrzej Krzemienski
: Hi, I have two questions connected to thread interruption in Boost.Thread.
*1.* The docs say that interrupt_and_join_if_joinable is defined as follows:
``` struct interrupt_and_join_if_joinable{
void operator()(thread& t) { t.interrupt(); if (t.joinable()) { t.join(); } }};
```
Sorry, let me continue with the question. Is there a reason why t.interrupt() is called without checking if t is joinable? This looks uncomfortable to me that I would be potentially calling interrupt() on a not-a-thread. Interrupting a not-a-thread should do nothing. I will add this to the reference documentation. However nothing prevents to implement it this way
void operator()(thread& t) { if (t.joinable()) { t.interrupt(); t.join(); } }}; I will do it.
*2.* When I make a call to this_thread::wait_for(),
blocking for a long time in thread t2, and the instant later I call t2.interrupt() from another thread t1. Do I have to wait the long time until wait_for() stops blocking t2, or does thread_interrupted get called 'immediately' after interrupt() is called from t1? It depends. If sleep_for is implemented using nanosleep()/pthread_delay_np() there is no way to throw the
Do you mean sleep_for here? thread_interrupted exception. However, if it is implemented waiting on a condition variable wait_for, then the exception will be throw before the duration elapses. Currently, sleep_for make use of nanosleep/pthread_delay_np when available. The advantage been that the sleep is steady/monotonic.
*3.* Does the support for interruption points require the other synchronization operations (like locks on mutexes) to be slower (in order to monitor interruption requests)? Not for locks and mutex, but yes it will be a little bit slower for condition variables, as we need to store the condition variable on which a thread could be waiting for.
I've on my TODO list a task to build interuptible threads on top of raw threads, but this will need to have also specific condition variables :( Best, Vicente
2016-04-19 20:36 GMT+02:00 Vicente J. Botet Escriba < vicente.botet@wanadoo.fr>:
Le 18/04/2016 23:50, Andrzej Krzemienski a écrit :
2016-04-18 23:42 GMT+02:00 Andrzej Krzemienski
: Hi,
I have two questions connected to thread interruption in Boost.Thread.
*1.* The docs say that interrupt_and_join_if_joinable is defined as follows:
``` struct interrupt_and_join_if_joinable{
void operator()(thread& t) { t.interrupt(); if (t.joinable()) { t.join(); } }};
```
Sorry, let me continue with the question. Is there a reason why t.interrupt() is called without checking if t is joinable? This looks uncomfortable to me that I would be potentially calling interrupt() on a not-a-thread.
Interrupting a not-a-thread should do nothing. I will add this to the reference documentation. However nothing prevents to implement it this way
void operator()(thread& t) { if (t.joinable()) { t.interrupt(); t.join(); } }};
I will do it.
Hi Vicente, thanks for the reply.
*2.* When I make a call to this_thread::wait_for(),
Do you mean sleep_for here?
Yes :) sleep_for(). But in general, my concern applies to any operation that can potentially block.
blocking for a long
time in thread t2, and the instant later I call t2.interrupt() from another thread t1. Do I have to wait the long time until wait_for() stops blocking t2, or does thread_interrupted get called 'immediately' after interrupt() is called from t1?
It depends. If sleep_for is implemented using nanosleep()/pthread_delay_np() there is no way to throw the thread_interrupted exception. However, if it is implemented waiting on a condition variable wait_for, then the exception will be throw before the duration elapses.
Currently, sleep_for make use of nanosleep/pthread_delay_np when available. The advantage been that the sleep is steady/monotonic.
So, I understand that this means that the interface (as opposed to the current or any future implementation) can only guarantee that in the worst case thread_interrupted is called *after* the operation unblocks the thread. Does the same guarantee apply to other blocking operations on mutex and or conditional variables?
*3.* Does the support for interruption points require the other
synchronization operations (like locks on mutexes) to be slower (in order to monitor interruption requests)?
Not for locks and mutex, but yes it will be a little bit slower for condition variables, as we need to store the condition variable on which a thread could be waiting for.
I've on my TODO list a task to build interuptible threads on top of raw threads, but this will need to have also specific condition variables :(
Perhaps I owe you some background on these questions. I wanted to use boost::thread in place of std::thread in my job just because of this interruption mechanism that I would otherwise need to implement manually. But other colleagues raised concerns about what guarantees are really offered by the interruption mechanism. Regards, &rzej
Le 20/04/2016 08:52, Andrzej Krzemienski a écrit :
2016-04-19 20:36 GMT+02:00 Vicente J. Botet Escriba < vicente.botet@wanadoo.fr>:
Le 18/04/2016 23:50, Andrzej Krzemienski a écrit :
2016-04-18 23:42 GMT+02:00 Andrzej Krzemienski
: Hi,
I have two questions connected to thread interruption in Boost.Thread.
*1.* The docs say that interrupt_and_join_if_joinable is defined as follows:
``` struct interrupt_and_join_if_joinable{
void operator()(thread& t) { t.interrupt(); if (t.joinable()) { t.join(); } }};
```
Sorry, let me continue with the question. Is there a reason why t.interrupt() is called without checking if t is joinable? This looks uncomfortable to me that I would be potentially calling interrupt() on a not-a-thread.
Interrupting a not-a-thread should do nothing. I will add this to the reference documentation. However nothing prevents to implement it this way
void operator()(thread& t) { if (t.joinable()) { t.interrupt(); t.join(); } }};
I will do it.
Hi Vicente, thanks for the reply.
*2.* When I make a call to this_thread::wait_for(), Do you mean sleep_for here?
Yes :) sleep_for(). But in general, my concern applies to any operation that can potentially block.
blocking for a long
time in thread t2, and the instant later I call t2.interrupt() from another thread t1. Do I have to wait the long time until wait_for() stops blocking t2, or does thread_interrupted get called 'immediately' after interrupt() is called from t1?
It depends. If sleep_for is implemented using nanosleep()/pthread_delay_np() there is no way to throw the thread_interrupted exception. However, if it is implemented waiting on a condition variable wait_for, then the exception will be throw before the duration elapses.
Currently, sleep_for make use of nanosleep/pthread_delay_np when available. The advantage been that the sleep is steady/monotonic.
So, I understand that this means that the interface (as opposed to the current or any future implementation) can only guarantee that in the worst case thread_interrupted is called *after* the operation unblocks the thread. Right. Does the same guarantee apply to other blocking operations on mutex and or conditional variables? No. For mutex and condition_variable timed operations the interruption is throw as soon as interrupt is called. Only sleep make use of nonosleep.
*3.* Does the support for interruption points require the other
synchronization operations (like locks on mutexes) to be slower (in order to monitor interruption requests)?
Not for locks and mutex, but yes it will be a little bit slower for condition variables, as we need to store the condition variable on which a thread could be waiting for.
I've on my TODO list a task to build interuptible threads on top of raw threads, but this will need to have also specific condition variables :(
Perhaps I owe you some background on these questions. I wanted to use boost::thread in place of std::thread in my job just because of this interruption mechanism that I would otherwise need to implement manually. But other colleagues raised concerns about what guarantees are really offered by the interruption mechanism. I understand their concerns. Hoping the guaranties are clearer now. Let me know if you want some additional clarifications.
Best, Vicente
participants (2)
-
Andrzej Krzemienski
-
Vicente J. Botet Escriba