[Boost.Threads] Exiting Thread Properly

Hi, I'm new to Boost.Threads and have previously been using Windows events to signal threads to shut down. Since the Boost.Threads library does not include an Event type I'm wondering what the best approach is to signal a thread to exit. Let's say the thread is a worker thread which loops around every time it has finished its job and then wants to determine if it should shut down or not. Thanks, Soren

I'm wondering what the best approach is to signal a thread to exit. Just allocate a boolean variable for each thread and pass the address to
Soren Dreijer wrote:
the thread starting function. The loop of the thread breaks if the flag
is reset; the thread exits. This scheme is so simple that it doesn't
even require synchronization beyond making the pointer the thread
accesses volatile.
You could use a shared_ptr to manage the memory, but personally I would
simply use a scoped_ptr in the thread's main function.
The following code is conceptual. I can't remember the exact API of
Boost.Threads.
void thread_proc(volatile bool *flag)
{
scoped_ptr<bool> guard(flag);
while(*flag) {
// Work
}
}
map

Roland Schwarz wrote:
What makes you believe, you need not protect access to the shared flag? It would be ok, if you knew flag is atomic, but in general you will create non portable code this way.
What makes me believe it is that there will ever only be one writer. You cannot exactly determine when the slave thread stops. It only checks the flag once per iteration anyway. What's the worst thing that can happen if the flag is not atomic? The slave thread runs one more iteration. Makes no difference. The thread might also have just finished checking the flag before you set it. You'd have to put the entire loop, i.e. the check for the flag and the subsequent work item, under a mutex to ensure that the thread doesn't do any work anymore after the flag is set. Of course that means that the thread stopping function will block until the mutex becomes free. There is no guarantee that the thread won't perform any more work from the moment the stopping function is called. There merely is a guarantee that the thread has stopped processing by the time the canceller returns, and you can achieve the same effect cheaper (because the worker thread doesn't operate under a mutex) by just joining with the worker thread in the canceller. The only possible issue is CPU-specific caches in a multi-CPU system. However, I believe the volatile pointer should ensure that the value propagates to all CPUs. (You might want to make the pointer in the canceller volatile, too.) Is there any issue that I'm not aware of? Can the reader thread somehow "undo" the write because the write isn't atomic? Sebastian Redl

Sebastian Redl wrote:
What makes me believe it is that there will ever only be one writer.
Your code does not enforce this in any way. Besides this it never is safe to access any shared data item from multiple threads, even if it is for reading only. The only exception is when you know for sure, that the access is atomic. The C++ standards does not give you any guarantees on this. (But work is in progess.) Also your code might suffer from another problem: What does guarantee that the thread has not already ended, when you are calling into signal_worker. i->second might point to released memory at this time. About volatile: while it might not hurt in your usage case, believing volatile is enough for multiprocessor is wrong. Volatile does not give you any guarantees on memory ordering. To summarize: Your suggested code might work on a specific platfform/compiler but is nonportable, and thus dangerous. If you absolutely need it, you should properly encapsulate it or mark it clearly as such. Roland

On 12/28/06, Roland Schwarz
Sebastian Redl wrote:
What makes me believe it is that there will ever only be one writer.
Your code does not enforce this in any way.
Besides this it never is safe to access any shared data item from multiple threads, even if it is for reading only. The only exception is when you know for sure, that the access is atomic. The C++ standards does not give you any guarantees on this. (But work is in progess.)
If you talk about C++ standard then nothing is guaranteed at all about threading, since there isnt anything in the current standard about it. Nor about atomic access, so atomic access is too platform specific.
[snipped]
Roland
best regards, -- Felipe Magno de Almeida

Felipe Magno de Almeida wrote:
If you talk about C++ standard then nothing is guaranteed at all about threading, since there isnt anything in the current standard about it. Nor about atomic access, so atomic access is too platform specific.
Didn't I say so? I just mentioned, that there is work going on in the standards committee to change this. I never maintained that the current standard does say anything about threading. I also tried to convince the original poster, if he needs to use the shown code, he should be aware that it's usage isn't covered by the standard at all. Roland
participants (4)
-
Felipe Magno de Almeida
-
Roland Schwarz
-
Sebastian Redl
-
Soren Dreijer