Q: Stopping threads (Win32) or... the mysterious case of the thread with split personality
Hello, I would like to ask the group if you know of an efficient and clean way to stop a thread. What I've been using till now was a while loop in the function operator()() given to the boost::thread when created, whose condition was a boolean data member. This boolean was the means to stop the thread, such that when it was turned off, the child thread would exit the while loop and join the main thread. I am seeing now that this data member is being held twice (one copy for the main thread and one copy for the child thread) and there's no synch between the two copies; so when the main thread turns it off / false, the child thread goes on (since its copy is still on / true) and hell breaks loose. I am using VC7 in debug mode, so I started looking for some kind of flag/optimization I might be inadvertently using that makes data members into registers (thus explaining the copies), but couldn't find anything of the sort. Any help will be greatly appreciated... Dan --- Outgoing mail is certified Virus Free. Checked by AVG anti-virus system (http://www.grisoft.com). Version: 6.0.805 / Virus Database: 547 - Release Date: 03-Dec-04
First, a thread should kill itself. Second, you should use legit inter-thread communication. The request to commit suicide should be one of the things the thread pends on. Don't know boost.threads, but thats the general correct way to write a multi-threaded application. Dan Dimerman wrote:
Hello,
I would like to ask the group if you know of an efficient and clean way to stop a thread. What I've been using till now was a while loop in the function operator()() given to the boost::thread when created, whose condition was a boolean data member. This boolean was the means to stop the thread, such that when it was turned off, the child thread would exit the while loop and join the main thread. I am seeing now that this data member is being held twice (one copy for the main thread and one copy for the child thread) and there's no synch between the two copies; so when the main thread turns it off / false, the child thread goes on (since its copy is still on / true) and hell breaks loose.
I am using VC7 in debug mode, so I started looking for some kind of flag/optimization I might be inadvertently using that makes data members into registers (thus explaining the copies), but couldn't find anything of the sort.
Any help will be greatly appreciated...
Dan
--- Outgoing mail is certified Virus Free. Checked by AVG anti-virus system (http://www.grisoft.com). Version: 6.0.805 / Virus Database: 547 - Release Date: 03-Dec-04
Hello Jeffrey and thank you for your response,
As you point out, and is my general understanding, the thread indeed does
kills itself by exiting its main loop. My question pointed more towards what
you call "legit inter-thread" communication: I thought a shared variable
would be enough, given there is only one state transition (true to false),
just two threads and one is consistently the writer and the other
consistently the reader. What I see (debugger) is that from inside one
thread (main) the value of this variable is false, and from the other thread
(worker) the value is different !
"Jeffrey Holle"
First, a thread should kill itself. Second, you should use legit inter-thread communication. The request to commit suicide should be one of the things the thread pends on. Don't know boost.threads, but thats the general correct way to write a multi-threaded application.
Dan Dimerman wrote:
Hello,
I would like to ask the group if you know of an efficient and clean way to stop a thread. What I've been using till now was a while loop in the function operator()() given to the boost::thread when created, whose condition was a boolean data member. This boolean was the means to stop the thread, such that when it was turned off, the child thread would exit the while loop and join the main thread. I am seeing now that this data member is being held twice (one copy for the main thread and one copy for the child thread) and there's no synch between the two copies; so when the main thread turns it off / false, the child thread goes on (since its copy is still on / true) and hell breaks loose.
I am using VC7 in debug mode, so I started looking for some kind of flag/optimization I might be inadvertently using that makes data members into registers (thus explaining the copies), but couldn't find anything of the sort.
Any help will be greatly appreciated...
Dan
--- Outgoing mail is certified Virus Free. Checked by AVG anti-virus system (http://www.grisoft.com). Version: 6.0.805 / Virus Database: 547 - Release Date: 03-Dec-04
--- Outgoing mail is certified Virus Free. Checked by AVG anti-virus system (http://www.grisoft.com). Version: 6.0.805 / Virus Database: 547 - Release Date: 03-Dec-04
In general you do not want any thread pooling some variable. A background thead almost always has to pend, that is wait suspended, in a useful multi-threaded application. The trick is finding the way to pend on multiple events. Any decent threading library will provide a way. Dan Dimerman wrote:
Hello Jeffrey and thank you for your response,
As you point out, and is my general understanding, the thread indeed does kills itself by exiting its main loop. My question pointed more towards what you call "legit inter-thread" communication: I thought a shared variable would be enough, given there is only one state transition (true to false), just two threads and one is consistently the writer and the other consistently the reader. What I see (debugger) is that from inside one thread (main) the value of this variable is false, and from the other thread (worker) the value is different !
"Jeffrey Holle"
wrote in message news:covlls$he0$1@sea.gmane.org... First, a thread should kill itself. Second, you should use legit inter-thread communication. The request to commit suicide should be one of the things the thread pends on. Don't know boost.threads, but thats the general correct way to write a multi-threaded application.
Dan Dimerman wrote:
Hello,
I would like to ask the group if you know of an efficient and clean way to stop a thread. What I've been using till now was a while loop in the function operator()() given to the boost::thread when created, whose condition was a boolean data member. This boolean was the means to stop the thread, such that when it was turned off, the child thread would exit the while loop and join the main thread. I am seeing now that this data member is being held twice (one copy for the main thread and one copy for the child thread) and there's no synch between the two copies; so when the main thread turns it off / false, the child thread goes on (since its copy is still on / true) and hell breaks loose.
I am using VC7 in debug mode, so I started looking for some kind of flag/optimization I might be inadvertently using that makes data members into registers (thus explaining the copies), but couldn't find anything of the sort.
Any help will be greatly appreciated...
Dan
--- Outgoing mail is certified Virus Free. Checked by AVG anti-virus system (http://www.grisoft.com). Version: 6.0.805 / Virus Database: 547 - Release Date: 03-Dec-04
--- Outgoing mail is certified Virus Free. Checked by AVG anti-virus system (http://www.grisoft.com). Version: 6.0.805 / Virus Database: 547 - Release Date: 03-Dec-04
Are you passing your functor with boost::ref when creating the thread?
Otherwise it will make a copy.
On Sun, 5 Dec 2004 21:07:52 +0200, Dan Dimerman
Hello Jeffrey and thank you for your response,
As you point out, and is my general understanding, the thread indeed does kills itself by exiting its main loop. My question pointed more towards what you call "legit inter-thread" communication: I thought a shared variable would be enough, given there is only one state transition (true to false), just two threads and one is consistently the writer and the other consistently the reader. What I see (debugger) is that from inside one thread (main) the value of this variable is false, and from the other thread (worker) the value is different !
"Jeffrey Holle"
wrote in message news:covlls$he0$1@sea.gmane.org... First, a thread should kill itself. Second, you should use legit inter-thread communication. The request to commit suicide should be one of the things the thread pends on. Don't know boost.threads, but thats the general correct way to write a multi-threaded application.
Dan Dimerman wrote:
Hello,
I would like to ask the group if you know of an efficient and clean way to stop a thread. What I've been using till now was a while loop in the function operator()() given to the boost::thread when created, whose condition was a boolean data member. This boolean was the means to stop the thread, such that when it was turned off, the child thread would exit the while loop and join the main thread. I am seeing now that this data member is being held twice (one copy for the main thread and one copy for the child thread) and there's no synch between the two copies; so when the main thread turns it off / false, the child thread goes on (since its copy is still on / true) and hell breaks loose.
I am using VC7 in debug mode, so I started looking for some kind of flag/optimization I might be inadvertently using that makes data members into registers (thus explaining the copies), but couldn't find anything of the sort.
Any help will be greatly appreciated...
Dan
--- Outgoing mail is certified Virus Free. Checked by AVG anti-virus system (http://www.grisoft.com). Version: 6.0.805 / Virus Database: 547 - Release Date: 03-Dec-04
--- Outgoing mail is certified Virus Free. Checked by AVG anti-virus system (http://www.grisoft.com). Version: 6.0.805 / Virus Database: 547 - Release Date: 03-Dec-04
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
-- Cory Nelson http://www.int64.org
Hello Cory,
Thank you for your response.
No, I'm ashamed to say, I didn't pass a boost::ref to the boost::thread.
And you sir, have hit a bull's eye.
Thanks again.
Dan
"Cory Nelson"
Are you passing your functor with boost::ref when creating the thread? Otherwise it will make a copy.
On Sun, 5 Dec 2004 21:07:52 +0200, Dan Dimerman
wrote: Hello Jeffrey and thank you for your response,
As you point out, and is my general understanding, the thread indeed does kills itself by exiting its main loop. My question pointed more towards what you call "legit inter-thread" communication: I thought a shared variable would be enough, given there is only one state transition (true to false), just two threads and one is consistently the writer and the other consistently the reader. What I see (debugger) is that from inside one thread (main) the value of this variable is false, and from the other thread (worker) the value is different !
"Jeffrey Holle"
wrote in message news:covlls$he0$1@sea.gmane.org... First, a thread should kill itself. Second, you should use legit inter-thread communication. The request to commit suicide should be one of the things the thread pends on. Don't know boost.threads, but thats the general correct way to write a multi-threaded application.
Dan Dimerman wrote:
Hello,
I would like to ask the group if you know of an efficient and clean way to stop a thread. What I've been using till now was a while loop in the function operator()() given to the boost::thread when created, whose condition was a boolean data member. This boolean was the means to stop the thread, such that when it was turned off, the child thread would exit the while loop and join the main thread. I am seeing now that this data member is being held twice (one copy for the main thread and one copy for the child thread) and there's no synch between the two copies; so when the main thread turns it off / false, the child thread goes on (since its copy is still on / true) and hell breaks loose.
I am using VC7 in debug mode, so I started looking for some kind of flag/optimization I might be inadvertently using that makes data members into registers (thus explaining the copies), but couldn't find anything of the sort.
Any help will be greatly appreciated...
Dan
--- Outgoing mail is certified Virus Free. Checked by AVG anti-virus system (http://www.grisoft.com). Version: 6.0.805 / Virus Database: 547 - Release Date: 03-Dec-04
--- Outgoing mail is certified Virus Free. Checked by AVG anti-virus system (http://www.grisoft.com). Version: 6.0.805 / Virus Database: 547 - Release Date: 03-Dec-04
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
-- Cory Nelson http://www.int64.org
--- Outgoing mail is certified Virus Free. Checked by AVG anti-virus system (http://www.grisoft.com). Version: 6.0.806 / Virus Database: 548 - Release Date: 05-Dec-04
Dan Dimerman wrote:
Hello Cory, Thank you for your response. No, I'm ashamed to say, I didn't pass a boost::ref to the boost::thread. And you sir, have hit a bull's eye. <snip>
That still won't solve your problem, in general. Multithreading is an entirely non-standard extension to C++. Libraries like Boost.Thread go part way to providing portability, but memory semantics are troublesome. Actual implementations do not guarantee that changes to memory in one thread become visible in another thread in the same order, or at all. You should protect all access to the controlling flag with a mutex. In this case it would probably be sufficient to use the "volatile" qualifier on the controlling member, but this is not generally a good solution. Ben.
"Ben Hutchings"
That still won't solve your problem, in general. Multithreading is an / ... / You should protect all access to the controlling flag with a mutex. In this case it would probably be sufficient to use the "volatile" qualifier on the controlling member, but this is not generally a good solution. Ben.
In this case, I think the problem was that by {mis,ab,}using the boost thread lib, I passed a copy of the functor that would be the worker thread instead of just a reference to it, hence the duplicity. Protecting that variable with a mutex wouldn't have had any effect, since there would have been two copies still. regards... Dan --- Outgoing mail is certified Virus Free. Checked by AVG anti-virus system (http://www.grisoft.com). Version: 6.0.806 / Virus Database: 548 - Release Date: 05-Dec-04
Dan Dimerman wrote:
"Ben Hutchings"
wrote in message news:41B47000.1030500@businesswebsoftware.com... That still won't solve your problem, in general. Multithreading is an / ... / You should protect all access to the controlling flag with a mutex. In this case it would probably be sufficient to use the "volatile" qualifier on the controlling member, but this is not generally a good solution. Ben.
In this case, I think the problem was that by {mis,ab,}using the boost thread lib, I passed a copy of the functor that would be the worker thread instead of just a reference to it, hence the duplicity. Protecting that variable with a mutex wouldn't have had any effect, since there would have been two copies still.
I realise that, but I think eliminating the copy only solves half the problem. Ben.
participants (4)
-
Ben Hutchings
-
Cory Nelson
-
Dan Dimerman
-
Jeffrey Holle