Boost logo

Boost :

Subject: Re: [boost] Boost sprint: #3407 boost::call_once not re-entrant (at least in win32)
From: Anthony Williams (anthony.ajw_at_[hidden])
Date: 2009-11-23 12:26:09


Gottlob Frege <gottlobfrege_at_[hidden]> writes:

> On Mon, Nov 23, 2009 at 6:46 AM, Anthony Williams <anthony.ajw_at_[hidden]> wrote:
>> I would just go for adding a "running" state to the flag value. If the
>> flag is not "complete", set it to "running" using CAS. If we set it,
>> then run, otherwise create an event, store it in the once_flag object
>> (using CAS in case another waiter already stored an event), check the
>> flag is still "running" and then wait for our event. When the event is
>> triggered, loop again (to run the function if it threw last time).
>>
>> Once the thread that runs the function has completed the function call
>> it can then set the flag to "complete", and set the event if there is
>> one. If the function throws then the flag can be set back to "not
>> started" and the event set if there is one.

> Yes, I've done it this way. You will have problems destroying the
> event. ie knowing who and when to destroy it. I don't think leaving
> the event handle leaking would be OK. You need to count it.

Yep.

> It
> really isn't *too* hard, until you run into exceptions.

It's not that bad even then. Just use RAII to decrement the count on the
way out.

> Then you need
> to open the event and reset the once_flag. But now you need another
> event for the new attempt (you can't use the same event as you are not
> sure if all threads from the first attempt have even waited yet). So
> where do you store the event!? Using nodes solves that.

You don't need a new event. If the event is set it means "check the
status". So thread enters call_once. Sees status is "running" and waits
on the event. When the event is set it wakes and checks status. If
status is complete, we're done. If status is running, wait for the same
event again. If status is "not done", set it to running, reset the event
and run the function. On completion, set status to "complete" and set
the event. On exception, set status to "not done" and set the event.

I'll code it up.

Anthony

-- 
Author of C++ Concurrency in Action | http://www.stdthread.co.uk/book/
just::thread C++0x thread library   | http://www.stdthread.co.uk
Just Software Solutions Ltd         | http://www.justsoftwaresolutions.co.uk
15 Carrallack Mews, St Just, Cornwall, TR19 7UL, UK. Company No. 5478976

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