[thread] C++11 once_flag enabled when constexpr is not available

Hi, Vicente! I see you applied my patch for call_once but you seem to forgot to disable the C++11 call_once interface when the compiler does not support constexpr. Was that intentional or you just missed it? Anyway, please find the patch attached.

Le 22/02/13 23:49, Andrey Semashev a écrit :
Hi, Vicente!
I see you applied my patch for call_once but you seem to forgot to disable the C++11 call_once interface when the compiler does not support constexpr. Was that intentional or you just missed it?
Anyway, please find the patch attached.
Hi Andrey, In your patch you say +// For C++11 call_once interface the compiler MUST support constexpr. +// Otherwise once_flag would be initialized during dynamic initialization stage, which is not thread-safe. I'm not an expert on the C++11 wording. Could you elaborate why once_flag would be initialized during dynamic initialization stage? Thanks in advance, Vicente

On Tue, Mar 5, 2013 at 4:31 PM, Vicente J. Botet Escriba <vicente.botet@wanadoo.fr> wrote:
Le 22/02/13 23:49, Andrey Semashev a écrit :
Hi, Vicente!
I see you applied my patch for call_once but you seem to forgot to disable the C++11 call_once interface when the compiler does not support constexpr. Was that intentional or you just missed it?
Anyway, please find the patch attached.
Hi Andrey,
In your patch you say
+// For C++11 call_once interface the compiler MUST support constexpr. +// Otherwise once_flag would be initialized during dynamic initialization stage, which is not thread-safe.
I'm not an expert on the C++11 wording. Could you elaborate why once_flag would be initialized during dynamic initialization stage?
It's covered in 3.6.2/2. In particular: <quote-C++11> Variables with static storage duration (3.7.1) or thread storage duration (3.7.2) shall be zero-initialized (8.5) before any other initialization takes place. Constant initialization is performed: ... — if an object with static or thread storage duration is initialized by a constructor call, if the constructor is a constexpr constructor, if all constructor arguments are constant expressions (including conversions), and if, after function invocation substitution (7.1.5), every constructor call and full-expression in the mem-initializers and in the brace-or-equal-initializers for non-static data members is a constant expression; — if an object with static or thread storage duration is not initialized by a constructor call and if every full-expression that appears in its initializer is a constant expression. Together, zero-initialization and constant initialization are called static initialization; all other initialization is dynamic initialization. Static initialization shall be performed before any dynamic initialization takes place. </quote-C++11> The C++11 once_flag has constexpr constructor, which makes it suitable for constant initialization and thread-safe. Now, if the compiler does not support constexpr, and once_flag still has non-trivial constructor (that's the case with Boost.Thread implementation), the once_flag initialization is performed at dynamic initialization. The only way to make it statically initialized is to remove the constructor and initialize it as an aggregate. It will then fall under the second quoted bullet. If the compiler implements C++03 then aggregate initialization is the only solution. Under 3.6.2/1: <quote-C++03> Objects with static storage duration (3.7.1) shall be zero-initialized (8.5) before any other initialization takes place. Zero-initialization and initialization with a constant expression are collectively called static initialization; all other initialization is dynamic initialization. Objects of POD types (3.9) with static stor- age duration initialized with constant expressions (5.19) shall be initialized before any dynamic initial- ization takes place. </quote-C++03> The fact that aggregate initialization is performed in the static initialization stage is warranted by 8.5.1/14: <quote-C++03> When an aggregate with static storage duration is initialized with a brace-enclosed initializer-list, if all the member initializer expressions are constant expressions, and the aggregate is a POD type, the initialization shall be done during the static phase of initialization (3.6.2) </quote-C++03>

On 5 March 2013 12:31, Vicente J. Botet Escriba wrote:
Le 22/02/13 23:49, Andrey Semashev a écrit :
Hi, Vicente!
I see you applied my patch for call_once but you seem to forgot to disable the C++11 call_once interface when the compiler does not support constexpr. Was that intentional or you just missed it?
Anyway, please find the patch attached.
Hi Andrey,
In your patch you say
+// For C++11 call_once interface the compiler MUST support constexpr. +// Otherwise once_flag would be initialized during dynamic initialization stage, which is not thread-safe.
I'm not an expert on the C++11 wording. Could you elaborate why once_flag would be initialized during dynamic initialization stage?
A non-constexpr constructor is a function call, which cannot happen during static initialization.
participants (3)
-
Andrey Semashev
-
Jonathan Wakely
-
Vicente J. Botet Escriba