From boost:thread documentation, it is clear that deleting a thread does not kill the thread. I very much approve of this. killing a thread is a very "strong" operation.
The problem is that there is now no connection between the system thread and the object itself, which (debatably) kills the idiom in C++ connection the object and the resource (I never remember its name). Was the idea of doing a "join()" in the dtor brought up? I.e., the dtor waiting for the thread to finish? I used it in my library, and it was _very_ effective, as I could _know_ that the thread and the object have parallel lifetimes, and it also helped me because it prevented many "thread-leakage" problems. Gil P.S. The question was - "Was the idea of doing a join() in the dtor ever brought up?"
--- In Boost-Users@y..., "giltayar"
From boost:thread documentation, it is clear that deleting a thread does not kill the thread. I very much approve of this. killing a thread is a very "strong" operation.
The problem is that there is now no connection between the system thread and the object itself, which (debatably) kills the idiom in C++ connection the object and the resource (I never remember its name).
Was the idea of doing a "join()" in the dtor brought up? I.e., the dtor waiting for the thread to finish? I used it in my library, and it was _very_ effective, as I could _know_ that the thread and the object have parallel lifetimes, and it also helped me because it prevented many "thread-leakage" problems.
Yes, but I'm not convinced it's appropriate. It would rarely be appropriate for a default constructed thread object (as in a self referencing thread object). In fact, unless you either make "join" callable multiple times (which was also suggested and hotly debated) and/or give some mechanism for a thread(func) constructed thread object to turn off the call in the destructor then it would *never* be possible for a default constructed thread object to call "join" in the destructor. Failing to call join() explicitly does not create a thread "leak". The thread is detached and clean up occurs according to those rules. The only problem is that if the main thread exits such detached threads may be immediately terminated (I say may, because most platforms have a "thread_exit" routine that prevents this from happening... any running threads must complete before the main thread returns from this call). I know this isn't the best solution, and this is specifically one of the areas I'm working on for the next release of Boost.Threads (as opposed to the next release(s) of Boost, which will contain only bug fixes). Bill Kempf
--- In Boost-Users@y..., "giltayar"
wrote: From boost:thread documentation, it is clear that deleting a
does not kill the thread. I very much approve of this. killing a thread is a very "strong" operation.
The problem is that there is now no connection between the system thread and the object itself, which (debatably) kills the idiom in C++ connection the object and the resource (I never remember its name).
Was the idea of doing a "join()" in the dtor brought up? I.e.,
dtor waiting for the thread to finish? I used it in my library, and it was _very_ effective, as I could _know_ that the thread and
object have parallel lifetimes, and it also helped me because it prevented many "thread-leakage" problems.
Yes, but I'm not convinced it's appropriate. It would rarely be appropriate for a default constructed thread object (as in a self referencing thread object). In fact, unless you either make "join" callable multiple times (which was also suggested and hotly debated) and/or give some mechanism for a thread(func) constructed thread object to turn off the call in the destructor then it would *never* be possible for a default constructed thread object to call "join" in the destructor.
Failing to call join() explicitly does not create a thread "leak". The thread is detached and clean up occurs according to those rules. The only problem is that if the main thread exits such detached threads may be immediately terminated (I say may, because most platforms have a "thread_exit" routine that prevents this from happening... any running threads must complete before the main
1. On the multi-join/default constructor issue:
Hmmm... hadn't noticed the default ctor. The multi-join issue is a
valid one. How I would solve it is for the dtor to "know" whether a
join was called (using a private member), i.e. whether thread is
alive or not, and thus know whether to join() it.
2. On the "leak":
How about this code:
void Foo (FooType& x)
{
MyFunction f(x);
boost:thread t(f);
// continue processing...
if (error-occured-during-processing)
throw std::exception("ouch");
// continue processing...
t.join();
}
As a user of RIIA (resource-initialization-is-acquisition), this code
would have looked apppropriate and OK. But it is wrong, because the
thread may be accessing f, which will be out of scope in case the
exception was thrown! To fix it, one should do...
void Foo (FooType& x)
{
MyFunction f(x);
boost:thread t(f);
try {
// continue processing...
if (error-occured-during-processing)
throw std::exception("ouch");
// continue processing...
t.join();
}
catch(...)
{
t.join();
throw;
}
}
This will now work, but is exactly the code that RIIA is trying to
remove. Now, if the dtor would have joined - everything would have
worked in the original code.
Actually, one could argue that if the dtor joins, then one does not
need a join() function! join() leaves the thread object in an invalid
state, which is (for me) a weird method. If we can do without join(),
then all for the better, and the code would be...
void Foo (FooType& x)
{
MyFunction f(x);
boost:thread t(f);
// continue processing...
if (error-occured-during-processing)
throw std::exception("ouch");
// continue processing...
}
Gil
P.S. Am I re-hashing previous conversations? In this mailing list
there is no searching capabilities, so I don't know.
--- In Boost-Users@y..., "bill_kempf"
returns from this call).
I know this isn't the best solution, and this is specifically one of the areas I'm working on for the next release of Boost.Threads (as opposed to the next release(s) of Boost, which will contain only bug fixes).
Bill Kempf
--- In Boost-Users@y..., "giltayar"
1. On the multi-join/default constructor issue:
Hmmm... hadn't noticed the default ctor. The multi-join issue is a valid one. How I would solve it is for the dtor to "know" whether a join was called (using a private member), i.e. whether thread is alive or not, and thus know whether to join() it.
Yes, it's possible, but the semantics result in something that's at least a little surprising to some, and possibly not valid for others.
2. On the "leak":
How about this code:
void Foo (FooType& x) { MyFunction f(x); boost:thread t(f); // continue processing... if (error-occured-during-processing) throw std::exception("ouch"); // continue processing... t.join(); }
As a user of RIIA (resource-initialization-is-acquisition), this code would have looked apppropriate and OK. But it is wrong, because the thread may be accessing f, which will be out of scope in case the exception was thrown! To fix it, one should do...
No, it won't access an out of scope f. Why? Because the thread never accesses f at all. It uses a *copy* of f, whose lifetime will remain valid. In any case, you're describing a different problem from a "thread leak", and the above code simply won't "leak".
P.S. Am I re-hashing previous conversations? In this mailing list there is no searching capabilities, so I don't know.
Sure there's searching. Are you using the YahooGroups web interface? Bill Kempf
giltayar wrote:
1. On the multi-join/default constructor issue:
Hmmm... hadn't noticed the default ctor. The multi-join issue is a valid one. How I would solve it is for the dtor to "know" whether a join was called (using a private member), i.e. whether thread is alive or not, and thus know whether to join() it.
Nah, *detach()* it -- if NOT already joined:
giltayar wrote:
1. On the multi-join/default constructor issue:
Hmmm... hadn't noticed the default ctor. The multi-join issue is a valid one. How I would solve it is for the dtor to "know" whether a join was called (using a private member), i.e. whether thread is alive or not, and thus know whether to join() it.
Nah, *detach()* it -- if NOT already joined: http://www.terekhov.de/mythread.c http://www.terekhov.de/thread_ptr.txt http://sources.redhat.com/pthreads-win32 regards, alexander.
participants (3)
-
Alexander Terekhov
-
bill_kempf
-
giltayar