Thread-safe initialisation of local statics: MSVC [duplicate] - c++

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Is static init thread-safe with VC2010?
I know that gcc and llvm-clang emit code to initialise local static variables in a threadsafe manner (which allows one to escape the static order initialisation fiasco by wrapping global statics in functions).
This msdn blog post, however, is the best documentation I can find of vcc's behaviour in these circumstances, and purports that static initialisation cannot ever be threadsafe, because the initialiser for a local static could recursively call into the same scope.
I don't buy this argument - it is clearly a programming error if the initialiser relies on its own result.
So, given that this article is from 2004, that gcc and clang can do it, and that the current msvc documentation is ambiguous (stating that 'assigning' to a local static isn't threadsafe, but nothing more):
Is the initialisation of local statics now threadsafe in MSVC?
If not, why not, since it is clearly possible for gcc to do this, but very difficult for the programmer to add in afterwards.

The C++0x Standard says:
§6.7 Declaration statement [stmt.dcl]
4/ The zero-initialization (8.5) of all block-scope variables with static storage duration (3.7.1) or thread storage duration (3.7.2) is performed before any other initialization takes place. Constant initialization (3.6.2) of a block-scope entity with static storage duration, if applicable, is performed before its block is first entered.
An implementation is permitted to perform early initialization of other block-scope variables with static or thread storage duration under the same conditions that an implementation is permitted to statically initialize a variable with static or thread storage duration in namespace scope (3.6.2). Otherwise such a variable is initialized the first time control passes through its declaration; such a variable is considered initialized upon the completion of its initialization.
If the initialization exits by throwing an exception, the initialization is not complete, so it will be tried again the next time control enters the declaration.
If control enters the declaration concurrently while the variable is being initialized, the concurrent execution shall wait for completion of the initialization.88
If control re-enters the declaration recursively while the variable is being initialized, the behavior is undefined.
[ Example:
int foo(int i) {
static int s = foo(2*i); // recursive call - undefined
return i+1;
}
—end example ]
88) The implementation must not introduce any deadlock around execution of the initializer.
As expected, it is quite complete.
However the fact is that even older versions of gcc already complied with this, and in fact do even better: in case of recursive initialization, an exception is thrown.
Finally, regarding a programmer adding it afterward: you can normally do it if you have something like Compare And Swap available, and use a sufficiently small variable, relying on zero-initialization of the variable to mark its non-computed state. However I do agree it's much easier if it's baked in.
I am afraid I stopped followed VC++ progresses though, so I don't know where it stands now. My only advice would be... look it up at assembly level.

I heard it is already implemented in vs2010, but can not find any reference. Anyway in c++0x standard such initializations are explicitly required to be thread-safe, so sooner or later ms would comply I guess.

Related

Is asignment of a local static reference thread-safe? [duplicate]

This question already has answers here:
Is Meyers' implementation of the Singleton pattern thread safe?
(6 answers)
Closed 5 years ago.
I know this is an often asked question, but as there are so many variants, I'd like to re-state it, and hopefully have an answer reflecting the current state. Something like
Logger& g_logger() {
static Logger lg;
return lg;
}
Is the constructor of variable lg guaranteed to run only once?
I know from previous answers that in C++03, this is not; in C++0x draft, this is enforced. But I'd like a clearer answer to
In C++11 standard (not draft), is the thread-safe initialization behavior finalized?
If the above is yes, in current latest releases of popular compilers, namely gcc 4.7, vc 2011 and clang 3.0, are they properly implemented?
The relevant section 6.7:
such a variable is initialized the first time control passes through its declaration; such a variable is considered initialized upon the completion of its initialization. [...] If control enters the declaration concurrently while the variable is being initialized, the concurrent execution shall wait for completion of the initialization.
Then there's a footnote:
The implementation must not introduce any deadlock around execution of the initializer.
So yes, you're safe.
(This says nothing of course about the subsequent access to the variable through the reference.)
--fno-threadsafe-statics also worth mentioning. In gcc:
Do not emit the extra code to use the routines specified in the C++ ABI for thread-safe initialization of local statics. You can use this option to reduce code size slightly in code that doesn't need to be thread-safe.
Also, have a look at the old thread Are function static variables thread-safe in GCC?

is (local) static initialization allowed to happen prematurley?

Lets say foo is called once in a program, and
void foo()
{
if(sometimes_false())
{
static int xx = func_with_sideeffect();
}
}
the condition wasn't met, is the side-effect
1. Allowed to have happened
2. Mandated to have happened (I'm guessing not if my compiler is conforming)
3. Mandated to not have happened
The non-constant initialization of all variable with local scope and static storage duration is from the point it is encountered till the end of the program. So, if the variable is not encountered because of a condition, it would not be initialized and the side effect won't happen.
The following quote from the standard supports the answer (particularly the part in bold)
6.7 Declaration statement [stmt.dcl]
The zero-initialization (8.5) of all block-scope variables with static
storage duration (3.7.1) or thread storage duration (3.7.2) is
performed before any other initialization takes place. Constant
initialization (3.6.2) of ablock-scope entity with static storage
duration, if applicable, is performed before its block is first
entered.An implementation is permitted to perform early initialization
of other block-scope variables with static orthread storage duration
under the same conditions that an implementation is permitted to
statically initializea variable with static or thread storage duration
in namespace scope (3.6.2). Otherwise such a variable is initialized
the first time control passes through its declaration; such a
variable is considered initialized upon the completion of its
initialization. If the initialization exits by throwing an exception,
the initialization is not complete, so it will be tried again the next
time control enters the declaration. If control enters the declaration
concurrently while the variable is being initialized, the concurrent
execution shall wait for completion of the initialization.88 If control
re-enters the declaration recursively while the variable is
being initialized, the behavior is undefined.
The answer is 3 but you need to think about threading.
The static int xx will be initialised by the first thread encountering that variable, and C++11 will block all other threads at that point until func_with_sideeffect() returns and the result has been assigned to xx. (That's not the case with older standards: a mutex would have been required).
It's more difficult to predict the destruction of xx if it was an instance of an object with a non-trivial destructor.

Thread safe singleton in C++ after gcc 4?

I heard that after some version of gcc using simply something like:
static A* a = new A();
return a;
Is thread-safe for a singleton and one wouldn't need something adapted from say http://locklessinc.com/articles/singleton_pattern/ anymore...
Does anyone have a specific reference or link to where I can read about this?
Section 6.7 of draft standard (n3337.pdf), point 4:
The zero-initialization (8.5) of all block-scope variables with static storage duration (3.7.1) or thread storage
duration (3.7.2) is performed before any other initialization takes place. Constant initialization (3.6.2) of a
block-scope entity with static storage duration, if applicable, is performed before its block is first entered.
An implementation is permitted to perform early initialization of other block-scope variables with static or
thread storage duration under the same conditions that an implementation is permitted to statically initialize
a variable with static or thread storage duration in namespace scope (3.6.2). Otherwise such a variable is
initialized the first time control passes through its declaration; such a variable is considered initialized upon
the completion of its initialization. If the initialization exits by throwing an exception, the initialization
is not complete, so it will be tried again the next time control enters the declaration. If control enters
the declaration concurrently while the variable is being initialized, the concurrent execution shall wait for
completion of the initialization.88 If control re-enters the declaration recursively while the variable is being
initialized, the behavior is undefined.
GCC follows the cross-vendor Itanium C++ ABI. The relevant sections covering thread-safe initialization of function-local statics are 2.8 Initialization guard variables and 3.3.2 One-time Construction API, which says:
An implementation that does not anticipate supporting multi-threading may simply check the first byte (i.e., the byte with lowest address) of that guard variable, initializing if and only if its value is zero, and then setting it to a non-zero value.
However, an implementation intending to support automatically thread-safe, one-time initialization (as opposed to requiring explicit user control for thread safety) may make use of the following API functions:
...
There were some bugs in the early GCC implementation of that API, I think they are all fixed and it works correctly from GCC version 4.3 (possibly earlier, I don't recall and can't find a reference right now.)
However, Singleton is a bad, bad pattern, do not use it!

Is local static variable initialization thread-safe in C++11? [duplicate]

This question already has answers here:
Is Meyers' implementation of the Singleton pattern thread safe?
(6 answers)
Closed 5 years ago.
I know this is an often asked question, but as there are so many variants, I'd like to re-state it, and hopefully have an answer reflecting the current state. Something like
Logger& g_logger() {
static Logger lg;
return lg;
}
Is the constructor of variable lg guaranteed to run only once?
I know from previous answers that in C++03, this is not; in C++0x draft, this is enforced. But I'd like a clearer answer to
In C++11 standard (not draft), is the thread-safe initialization behavior finalized?
If the above is yes, in current latest releases of popular compilers, namely gcc 4.7, vc 2011 and clang 3.0, are they properly implemented?
The relevant section 6.7:
such a variable is initialized the first time control passes through its declaration; such a variable is considered initialized upon the completion of its initialization. [...] If control enters the declaration concurrently while the variable is being initialized, the concurrent execution shall wait for completion of the initialization.
Then there's a footnote:
The implementation must not introduce any deadlock around execution of the initializer.
So yes, you're safe.
(This says nothing of course about the subsequent access to the variable through the reference.)
--fno-threadsafe-statics also worth mentioning. In gcc:
Do not emit the extra code to use the routines specified in the C++ ABI for thread-safe initialization of local statics. You can use this option to reduce code size slightly in code that doesn't need to be thread-safe.
Also, have a look at the old thread Are function static variables thread-safe in GCC?

c++ static POD initialization

I have a single instance of a simple POD
a.hpp
class A {
struct Zzz {
A* m_aPtr;
int m_val;
}
static Zzz s_zzz;
};
a.cpp
A::Zzz A::s_zzz;
I expect that both s_zzz.m_aPtr and s_zzz.m_val will be initialized to zeros before any other static initialization in any other compilation unit and it is guaranteed by the language itself. Am I right about it?
Usually I provide default constructors for the structs. Say
A::Zzz::Zzz() :
m_aPtr(0),
m_val(0)
{
}
Will it create initialization order problem or introduce compiler dependencies?
At least in C++0x, you can rely on all zero-initialization being performed before any other initialization code runs.
From the C++0x FCD, section [basic.start.init]
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.
If you're considering using this variable from other initialization code, then an explicit constructor would be a big mistake, as it would run sometime mixed in with other initialization code, and overwrite whatever changes have already been made by other initializers.
I expect that both s_zzz.m_aPtr and
s_zzz.m_val will be initialized to
zeros before any other static
initialization in any other
compilation unit and it is guaranteed
by the language itself.
It will be zero-initialized, since it's a static lifetime variable at namespace scope.
That zero-initialization happens before any dynamic initialization (an example of dynamic initializatin is when you some explicit initialization, or the class has a constructor).
The order of zero-initialization between different translation units is not defined, but there's not any way to detect it or rely on it since it happens before anything else, so it doesn't matter.
Re your point 2, it's rather unclear what you're asking about.
But for your static lifetime object, the effect is just that it's first zero-initialized, and then during dynamic initialization your constructor is used to zero it again (although the compiler might be smart enough to optimize away that redundant extra initialization).
Cheers & hth.,
ERRATA: Ben Voigt has provided a convincing example that the last paragraph above is wrong. So please disregard. The presence of the constructor means that the object can be dynamically initialized at some point before, between or after operations that change it, causing rather unpredictable results…
There are no guarantees about initialization order of statics between compilation units (see http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.14).
If it has a constructor, it will no longer be a POD, unfortunately.
Static data is always initialised to zero.
No it shouldn't introduce any initialisation problems.
When the application is loaded into memory, the static area is initialised to zero. This is before any code starts to execute.