Boost logo

Boost :

From: Howard Hinnant (hinnant_at_[hidden])
Date: 2007-03-27 12:33:13


On Mar 27, 2007, at 11:47 AM, Peter Dimov wrote:

>
>> join()
>> {
>> // Don't want to pretend to join with non-existent
>> // (or detached) thread, make noise
>> if (handle_ == 0)
>> throw ?;
>> while (!tl->done)
>> tl->cv1.wait();
>> detach(); // point of contention with N2178, makes join non-
>> const,
>> // and disables multi-join. Without it, resources
>> not
>> // released until explicit detach() or ~thread()
>> }
>>
> ... we can still remove this detach() call from join() and the user
> is free
> to get the old semantics back by just calling detach() explicitly
> after
> join() (whereas the reverse is not true).

Ok, I'm still having pain from realloc doing too much. :-) Maybe this
is a safe spot to tweak the pthreads semantics since ~thread() *must*
catch any leaks and C doesn't have that option. I've tweaked the
pseudo code as below and am continuing to look for problems with it.
I believe this comes closer to Anthony's earlier post. And note the
const qualifier I put on join!!! :-) (reserving the right to waffle
back...)

pthread_t handle_;
thread_local_data* tl;

detach()
{
     // If has already been detached, that means tl may already be
released
     // therefore not safe to go through twice.
     // But maybe ok to ignore subsequent detach?
     if (handle_ != 0)
     {
         tl->wait_on_owner = false;
         tl->cv2.notify_all();
         handle_ = 0;
     }
}

cancel()
{
     // Canceling a non-existent thread seems harmless
     if (handle_ != 0)
         tl->cancel_pending = true;
}

join() const
{
     // Don't want to pretend to join with non-existent
     // (or detached) thread, make noise
     if (handle_ == 0)
         throw ?;
     while (!tl->done)
         tl->cv1.wait();
}

thread::id get_id() const {return thread::id(handle_);}

~thread()
{
     cancel(); // harmless if already canceled
     detach(); // harmless if already detached
}

start()
{
     allocate_all_resources(); // tl != 0
     tl->done = false;
     tl->wait_on_owner = true;
     tl->cancel_pending = false;
     try
     {
         f();
     }
     catch (thread_canceled&)
     {
     }
     catch (...)
     {
         terminate();
     }
     tl->done = true;
     tl->cv1.notify_all();
     while (tl->wait_on_owner)
         tl->cv2.wait();
     release_all_resources(); // tl = 0
}

-Howard


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk