2

The Meyers Singleton depends on the fact that local static variable initialization is atomic.

I'm building something similar but I want the singleton to actually be one of a number of derived types. The base class getInstance() method should call a factory that will return the appropriate type.

My first idea is

static Foo *instance = FooFactory(...);

8.5p2 of N3337 seems to indicate that this is strictly initialization and not initialization and assignment and I interpret that to mean the entire statement is atomic. Is this correct?

If not would the statement

static Foo *instance(FooFactory(...));

be different?

Edit 8.5.2 -> 8.5.p2

Community
  • 1
  • 1
Michael Conlen
  • 1,959
  • 2
  • 17
  • 19

3 Answers3

1

Since C++11, initialization of static variables which are local to functions is atomic and thread safe, so yes, your lines of code is thread-safe and practically equivalent. (Syntax-wise your first version calls for copy constructor, but no compiler will generate it).

However, it is not clear what arguments are going to be provided to your Factory function and where are those going to be taken from?

SergeyA
  • 61,605
  • 5
  • 78
  • 137
  • 1
    Can you quote chapter and verse for initialization of static variables at *namespace scope* being thread safe? §6.7 [stmt.dcl] p4: says that "declaration statements" are thread safe, but I think that only applies to declarations at block scope. (in other words, static declarations inside a function). To be clear - it would be great if you can. – Martin Bonner supports Monica Aug 24 '16 at 19:07
  • @MartinBonner, never meant to say anything about namespace scope. The context of the question is certainly about function-scope static. Will clarify to be 100% clear. – SergeyA Aug 24 '16 at 19:33
  • I didn't read that into the question, but re-reading, I think you are right. Its an important caveat though, for other people who find this question via google later. – Martin Bonner supports Monica Aug 24 '16 at 19:38
1

variable_type variable_name = initializer is always initialization and not default construction and assignment. [dcl.init]/15 has

The initialization that occurs in the form

T x = a;

as well as in argument passing, function return, throwing an exception (15.1), handling an exception (15.3), and aggregate member initialization (8.5.1) is called copy-initialization. [ Note: Copy-initialization may invoke a move (12.8). —end note ]

Community
  • 1
  • 1
NathanOliver
  • 171,901
  • 28
  • 288
  • 402
1

8.5.2 is "[dcl.init.string]", and doesn't seem to be relevant. I think you mean 8.5 para2.

Yes, this is strictly initialization (specifically copy initialization - see 8.5 para14).

If the declaration is inside a function, then, as the answer to the linked question shows, all is well.

However if this is a static variable at namespace scope, then I can't see anything which requires the initialization to be thread safe. (That is only a problem if initialization creates threads - but I bet it does.)

Community
  • 1
  • 1
  • If a I aver see a static initialization which creates threads I would immediately raise concerns with the management about the developer who wrote it :) – SergeyA Aug 24 '16 at 19:35
  • Particularly exciting if we are talking about a Windows DLL - where doing almost anything inside DllMain (which is what does the static init), can lead to deadlock on the static loader lock :-) – Martin Bonner supports Monica Aug 24 '16 at 19:40