|
Boost : |
Subject: Re: [boost] [Boost.utility]
From: vicente.botet (vicente.botet_at_[hidden])
Date: 2010-01-27 17:47:07
----- Original Message -----
From: "Andrew Chinkoff" <achinkoff_at_[hidden]>
To: <boost_at_[hidden]>
Sent: Wednesday, January 27, 2010 10:48 PM
Subject: Re: [boost] [Boost.utility]
>
>
> Ok, I see. I would try to explain.
>
> Let us look at pseudo code:
<snip>
> *** BEGIN EXPLANATION ***
> Let us imagine that boost::call_once has approximately this implementation
> (in pseudo code):
>
> call_once(function foo)
> {
> if(!called)
> {
> Locker locker;
> if(!called)
> {
> called = true;
> foo(); (1)
> }
> }
> }
>
> If you insert foo code at line (1), you will see the cascade of nested
> blocks like this:
>
> if(!flag1)
> {
> Locker locker;
> if(!flag2) // "Double Check Locking"
> {
> Locker locker;
> if(!flag3) // "Triple Check Locking"
> {
> Locker locker;
> ...
> ...
> ...
> foo();
> ...
> ...
> ...
> }
> }
> }
>
<snip>
> I assume that boost::call_once does so:
>
> if(ATOMIC(!flag1)) // (2)
> {
> Locker locker;
> ...
> }
>
> I would like to ask Boost.Commutiny - is my assumption at line (2) the true?
> *** END OF EXPLANATION ***
>
> P.S. 1: Sorry for verbosity and complexity, if so.
>
Andrew, you don't need to make supossitions on how call_once works. Just see the current implementation for Posix systems (extracted from boost/thread/posinx/once.hpp):
template<typename Function>
void call_once(once_flag& flag,Function f)
{
static boost::uintmax_t const uninitialized_flag=BOOST_ONCE_INITIAL_FLAG_VALUE;
static boost::uintmax_t const being_initialized=uninitialized_flag+1;
boost::uintmax_t const epoch=flag.epoch;
boost::uintmax_t& this_thread_epoch=detail::get_once_per_thread_epoch();
if(epoch<this_thread_epoch)
{
pthread::pthread_mutex_scoped_lock lk(&detail::once_epoch_mutex);
while(flag.epoch<=being_initialized)
{
if(flag.epoch==uninitialized_flag)
{
flag.epoch=being_initialized;
try
{
pthread::pthread_mutex_scoped_unlock relocker(&detail::once_epoch_mutex);
f();
}
catch(...)
{
flag.epoch=uninitialized_flag;
BOOST_VERIFY(!pthread_cond_broadcast(&detail::once_epoch_cv));
throw;
}
flag.epoch=--detail::once_global_epoch;
BOOST_VERIFY(!pthread_cond_broadcast(&detail::once_epoch_cv));
}
else
{
while(flag.epoch==being_initialized)
{
BOOST_VERIFY(!pthread_cond_wait(&detail::once_epoch_cv,&detail::once_epoch_mutex));
}
}
}
this_thread_epoch=detail::once_global_epoch;
}
}
Now you can make a concrete request on a concrete implementation.
Best,
Vicente
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk