|
Boost : |
From: bill_kempf (williamkempf_at_[hidden])
Date: 2002-03-04 07:59:23
--- In boost_at_y..., "Yitzhak Sapir" <ysapir_at_y...> wrote:
> I want to initialize a "singleton" type object. To do this, I use
> call_once.
>
> void f()
> {
> call_once(inited, init_singleton);
> }
>
> basically. Now, after I init it, I want to use it in some way. So
then
> I have:
>
> void f()
> {
> call_once(inited, init_singleton);
> use_singleton();
> }
>
> Now, I was thinking that call_once may be called in a different
thread
> already by the time I get to use_singleton, but the singleton has
not
> been inited yet. So I added a mutex:
>
> void f()
> {
> call_once(inited, init_singleton);
> scoped_lock(singleton_mutex);
> use_singleton();
> }
>
> init_singleton()
> {
> scoped_lock(singleton_mutex);
> // do initialization
> }
>
> (I look at this now and am thinking this only reduces the possible
race
> condition but may, depending on the implementation of call_once, not
> eliminate it entirely). Now I want to call f() in a global
variable:
>
> struct some_global
> {
> some_global() { f(); }
> };
>
> some_global a_global;
>
> Now I have a worse condition, in which case the mutex, which is also
> global, may be constructed after the global. In this case, during
> call_once() in the call to f(), I'd end up waiting on a mutex that
> hasn't been constructed inside the scoped_lock. I could use
call_once
> to initialize the mutex, but I'd have to know what guarantees are
made
> regarding call_once to know if it solves the problem.
Particularly, I
> need to know, not only that "flag != once_init" is a postcondition
of
> call_once, but also that func() has completed execution. So, given
that
> I still have a race condition in the previous step, and given this
issue
> of unclear order of global initializations, how would it be best to
> solve this problem, or does call_once indeed guarantee this
> postcondition ("func() has executed at least one time.")?
The gaurantee is that "func() has been executed exactly once". It
must have been run before call_once() will return, and it will only
run once. As you note, any other gaurantees are not useful. I
thought the documentation was explicit about this, but I'll look at
it while I'm reworking the documentation.
> Btw, this may be the time to point out that the docs at
> http://www.boost.org/libs/thread/doc/call_once.html specify a const
> once_flag once_init, whereas the actual thing to document is: const
> once_flag BOOST_ONCE_INIT;
This is something that changed at one point, and I thought I had
gotten the documentation up to date with the code. I'll have to fix
this as well.
Thanks,
Bill Kempf
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk