|
Boost Users : |
From: giltayar (gil_at_[hidden])
Date: 2002-05-15 05:51:54
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_at_y..., "bill_kempf" <williamkempf_at_h...> wrote:
> --- In Boost-Users_at_y..., "giltayar" <gil_at_t...> wrote:
> > 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
Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net