|
Boost : |
From: Roland Schwarz (roland.schwarz_at_[hidden])
Date: 2006-10-06 08:58:01
Anthony Williams wrote:
> On Windows we don't need two calls to call_once, as my implementation allows
> passing an arbitrary functor, which can therefore have state (e.g. use bind to
> pass parameters).
I have been rethinking this. But it won't help. To solve the
initialization order problem we need the first call_one, to
initialize the list of destructor calls. The second will
initialize the instance. A call_once with parameters would
avoid solely the "reset" call to pass the instance pointer.
Note: The list of destructors is essential. Initially I tried to
embed a destructor within the class_once. While this is a valid
aggregate that can be statically initialized it still suffers
from a race condition. The compiler somehow has to emit code
that will schedule a call to the destructor of once_class.
Obviously this call can be scheduled when the code passes to
the declaration of the object. (I hit this in the MSVC case.)
So the only remedy I can see is to use aggregates without any
destructors and maintain a separate list that will be stepped
at atexit time.
With respect to your original suggestion, I found the post
where Bill Kempf already mentioned the idea:
http://lists.boost.org/Archives/boost/2002/08/33122.php
> Your code demonstrates how we could provide the same facility with pthreads,
> as an extension to call_once. Incidentally, whilst we're thinking about this,
> the POSIX spec says:
>
> "The behavior of pthread_once() is undefined if once_control has automatic
> storage duration or is not initialized by PTHREAD_ONCE_INIT."
>
> So we need to document this restriction on the use of boost::once_flag, unless
> you can find a way round it. This restriction doesn't apply on Windows, at
> least not with my implementation.
On the second reading I am not any more sure which "restriction" you are
talking about for Windows:
1) may not have automatic storage duration
2) must be explicitly initialized by PTHREAD_ONCE_INIT
Please don't get me wrong, but I would prefer having a statically
initializeable mutex, over having call_once. I'd rather like to
purge call_once entirely from the interface.
I suggested the wrapper primarily to make existing mutex types
statically initializeable and accidentally noted that this can
be extended to any default constuctible class.
My intent was to avoid the need to come up with distinct mutex
classes (which have to be written and maintained separately)
for that purpose.
I also do see absolutely no problem in requiring the user to
explicitly initialize. This also underpins its static nature.
Roland
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk