|
Boost : |
Subject: Re: [boost] Boost sprint: #3407 boost::call_once not re-entrant (at least in win32)
From: Gottlob Frege (gottlobfrege_at_[hidden])
Date: 2009-11-25 00:59:48
> I've checked in a new version on trunk
>
> https://svn.boost.org/svn/boost/trunk/boost/thread/win32/once.hpp
>
> This version only allocates an event if there is contention. The event
> (if there is one) is reset just before invoking the function in the one
> thread that gets to run it. It is set after the completion flag is
> set. The event is deallocated when the last thread that is using it
> exits call_once. If a thread exits because f() threw an exception then
> this is counted separately in order to avoid prematurely destroying the
> event. If f() throws every time it is called then the event will stick
> around until the flag is destroyed.
>
> It's not as tidy as I'd like, but I think the logic is sound.
>
Probably, except you never actually wait on the event! :-)
(or maybe I missed it).
I'm assuming you mean to wait on it after the 'waiting' thread
creates it if it doesn't exist:
if(!counted)
{
BOOST_INTERLOCKED_INCREMENT(&flag.count);
counted=true;
status=::boost::detail::interlocked_read_acquire(&flag.status);
if(status==function_complete_flag_value)
{
break;
}
event_handle=::boost::detail::interlocked_read_acquire(&flag.event_handle);
if(!event_handle)
{
event_handle=::boost::detail::allocate_event_handle(flag.event_handle);
continue;
}
***** Wait(event_handle); ****** ?
}
Also, once_flag is no longer a POD (because of the destructor). Not
sure if that is important. It is also now approx 4 * sizeof(long)
instead of just sizeof(long or pointer). :-(
Still looking at the overall algorithm...
Tony
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk