
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