Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Meyers singleton and dynamic libraries

Does the Meyers Singleton work in a scenario with dynamic libraries?
I.e. one library defining the singleton, others using it, each in its own compilation unit?
(I suppose it doesn't matter but the specific architecture is an application with frameworks on OS X)

I'm using the vanilla Meyers Singleton pattern: The following Instance() method is defined inline in the header file for a utility class (that's defined in a dynamic library):

    static Logger&  Instance()
              {
                 static Logger singletonInstance;
                 return singletonInstance;
              }

Copy constructor and operator= are declared private and not implemented, so we should be good, right?

Now if I link that library defining the singleton from the main app I can see the constructor being called multiple times.. with different addresses for this and all the weirdness I would expect when not having an actual singleton but multiple instances of the class.

So I'm wondering whether the dynamic library approach screws up the Meyers singleton or whether each compilation unit - library, main app - that includes the header for the singleton (effectively declaring and defining the Instance() method) will get "it's own singleton instance"?

Really not quite sure what to make of my observations so any hints much appreciated!

like image 905
ATV Avatar asked Jan 29 '14 21:01

ATV


1 Answers

You need to declare Instance in a header, and then define it in a dynamic library (presumably the same one that Logger is defined in). And you need to drop the static. And you need to make sure Instance has default visibility if you are using the visibility tools.

From your description, it sounds like you've defined this function in a header. This would give everyone who includes the header their own private definition of Instance, and thus their own private definition of the static Logger within Instance.

You could declare Instance inline, and that would give everything the semantics you expect (same as declaring in header and defining in the dylib). But my recommendation is to just do the inline to confirm what I'm telling you is correct (it is easy), and then outline into a dylib (and confirm again).

Once outlined, your design should work fine.

That being said, it is only guaranteed to work in C++11. That is, local statics are not thread safe in C++98/03, but are in C++11 and later. However, on OS X, they are thread safe even in C++03 language mode as an extension.

One other caveat: If you access Instance() in the atexit chain (or in a destructor of a global object), it is possible that your access will occur after the destruction of the static local singletonInstance within Instance(), causing undefined behavior. If you don't register things with atexit(), and if your global destructors don't call Instance(), you're safe. Otherwise you aren't. If you aren't safe, you can purposefully leak it:

Logger&  Instance()
{
   static Logger* singletonInstance = new Logger;
   return *singletonInstance;
}

This may cause some memory leak checkers to report false positives (or maybe they are true positives depending on your point of view), which is irritating.

like image 86
Howard Hinnant Avatar answered Sep 16 '22 15:09

Howard Hinnant