Boost logo

Boost :

Subject: Re: [boost] [thread] Can Boost.Thread use Boost.Atomic without falling on a compatibility issue?
From: Vicente J. Botet Escriba (vicente.botet_at_[hidden])
Date: 2013-01-13 13:32:04

Le 13/01/13 18:51, Andrey Semashev a écrit :
> On Sun, Jan 13, 2013 at 9:12 PM, Vicente J. Botet Escriba
> <vicente.botet_at_[hidden]> wrote:
>> Le 13/01/13 16:16, Andrey Semashev a écrit :
>>> once_flag must always be statically initialized, that's the key feature
>>> that
>>> allows call_once to be thread-safe. In C++03 this can only be guaranteed
>>> for
>>> POD types. C++11 also includes constant initialization into static
>>> initialization (i.e. when objects are initialized with constexpr
>>> constructors). All other objects are initialized during dynamic
>>> initialization, which is not thread-safe.
>> Thanks for clarifications, I understand your concern. The non-POD once_flag
>> implementation can not be used for static once_flag instances in a thread
>> safe mode.
>> Just for curiosity, from where comes the restriction that once_flag must
>> always be statically initialized? Could you point me to the standard?
> The standard only contains once_flag since C++11, and as you quoted
> its definition, it uses constexpr default constructor. The fact that
> it results in static initialization is outlined in 3.6.2/2.
> As for C++03, I cannot point you to a particular paper that defines
> once_flag; this is a matter of each particular implementation.
> However, it is known that dynamic initialization is just as unsafe in
> C++03 as it is in C++11, even more unsafe WRT function-local statics.
> In 3.6.2/1 in C++03 it is stated that "Objects of POD types (3.9) with
> static storage duration initialized with constant expressions (5.19)
> shall be initialized before any dynamic initialization takes place.",
> so one (if not the only one) way to implement once_flag safely is to
> make it a POD type.
> One thing still concerns me though with the C++11 code. The standard
> specifies that once_flag as non-copyable. This is quite reasonable
> when once_flag is used as described by the standard. OTOH,
> Boost.Thread supports the following code for backward compatibility:
> static once_flag flag = BOOST_ONCE_INIT;
> which expands to:
> static once_flag flag = once_flag();
> Technically, this invokes the default constructor and then the copy
> constructor. Compilers may be smart enough to optimize the copy away,
> which explains why it compiles. But I'm not quite sure this is still a
> constant initialization, especially considering the bug in clang (it
> defines implicit constructor without constexpr). To be on the safe
> side I would probably define a special explicit initializing
> constructor marked with constexpr so that the initialization could
> look like this:
> static once_flag flag = {0};
Well, the definition removes the copy constructor and the assignment

struct once_flag

After adding

static boost::once_flag once2 = BOOST_ONCE_INIT;

to example/once.cpp

and I'm seen the following kind of error on a lot of C++11 compilers

../example/once.cpp:16:33: error: use of deleted function
‘boost::once_flag::once_flag(const boost::once_flag&)’
In file included from ../../../boost/thread/once.hpp:19:0,
from ../example/once.cpp:10:
../../../boost/thread/pthread/once_atomic.hpp:37:5: error: declared here


../example/once.cpp:16:25: error: call to deleted constructor of
static boost::once_flag once2 = BOOST_ONCE_INIT;
^ ~~~~~~~~~~~~~~~
../../../boost/thread/pthread/once_atomic.hpp:37:30: note: function has
been explicitly marked deleted here
../../../boost/thread/detail/delete.hpp:42:35: note: expanded from macro
../../../boost/thread/detail/delete.hpp:20:7: note: expanded from macro
CLASS(CLASS const&) = delete; \

Maybe it is worth to add a portable extension to the C++11 to ensure

BTW, couldn't the lock scope be reduced as follows

BOOST_THREAD_DECL void commit_once_region(once_flag& flag) BOOST_NOEXCEPT
atomic_type& f = reinterpret_cast< atomic_type& >(;
{ // ++++++++
pthread::pthread_mutex_scoped_lock lk(&once_mutex);, memory_order_release);
} // ++++++++


Boost list run by bdawes at, gregod at, cpdaniel at, john at