Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

My singleton can be called multiple times

I have implemented an singleton based on c++ 11. However the constructor can be called multiple times in some cases.

The class will be compiled to static lib and used by other so lib (more than one so lib). And the system is a multi-thread system (run in the Android HAL level)

/// The .h file:

class Logger { public:      /// Return the singleton instance of Logger     static Logger& GetInstance() {         static Logger s_loggerSingleton;         return s_loggerSingleton;     }  private:      /// Constructor     Logger();     /// Destructor     ~Logger(); } 

/// the .cpp file

Logger::Logger() {    ALOGE("OfflineLogger create"); }  Logger::~Logger() {  } 

It should be created once eg:

03-21 01:52:20.785   728  4522 E         : OfflineLogger create 

However I can see it has been created more than once

03-21 01:52:20.785   728  4522 E         : OfflineLogger create 03-21 01:52:20.863   728  2274 E         : OfflineLogger create 03-21 01:52:20.977   728  2273 E         : OfflineLogger create 03-21 01:52:26.370   728  4522 E         : OfflineLogger create 

Questions:

  1. Anything wrong with my singleton design? Is it a thread-safe issue?

  2. Seems like my singleton works fine in one so scope, but each so lib which includes my singleton will create its own singleton, so that my singleton is no longer “be a singleton”. Is the problem caused from each dynamic linking to new so and the "static variable" becomes "local static"? Is it possible? If so, how to fix?

like image 385
hismart Avatar asked Apr 02 '19 05:04

hismart


People also ask

Can singleton class have multiple instances?

Well-designed singleton can have only one instance per application. Creating of multiple instances is a mistake in the application design. It might happen in some cases, e.g.: Non thread safe singleton with lazy initialization: several threads are trying to get an instance and creates multiple instances.

Why you should not use singletons?

By using singletons in your project, you start to create technical debt. Singletons tend to spread like a virus because it's so easy to access them. It's difficult to keep track of where they're used and getting rid of a singleton can be a refactoring nightmare in large or complex projects.

What's the downside of singleton?

Singletons hinder unit testing: A Singleton might cause issues for writing testable code if the object and the methods associated with it are so tightly coupled that it becomes impossible to test without writing a fully-functional class dedicated to the Singleton.

When singleton doesn't remain singleton in Java?

A singleton (in Java land) wouldn't work as a singleton if a given class is loaded by multiple class-loaders. Since a single class can exist (or can be loaded) in multiple classloaders, it's quite possible to have "multiple" instances of a "supposedly" singleton class for a given JVM instance.


2 Answers

  1. Anything wrong with my singleton design? Is it a thread-safe issue?

No. Initialization of function local static variables is guaranteed to be thread-safe by the standard.

  1. Seems like my singleton works fine in one so scope, but each so lib which include my singleton will create its own singleton, so that my singleton is no longer “be a singleton”. Is the problem caused from each dynamic linking to new so and the "staic veriable" become "local static"? Is it possible? If so, how to fix

That is the correct conclusion.

Instead of creating a static library that contains the implementation of the singleton, make it a dynamic library.

like image 159
R Sahu Avatar answered Sep 26 '22 00:09

R Sahu


Singletons are hard, especially with shared libraries.

Each of your shared libraries has an independent copy of the non-shared library. Without extra care, each will have a copy of the singleton.

In order to have non-trivial singletons, what I have had to do was

  1. Create an extremely low level library to help with singletons -- call it LibSingleton

  2. Create a singleton template that knows the type of the singleton. It uses magic statics to send a request to the LibSingleton with a size, typeid(T).name() key, and type-erased construction and destruction code. LibSingleton returns a reference counting RAII object.

  3. LibSingleton uses a shared mutex to either return a previously constructed object that matches the name/size or constructs it. If it constructs the object, it stores the destruction code.

  4. When the last reference-counted handle to the LibSingleton data goes away, LibSingleton runs the destruction code and cleans up the memory in its unordered map.

This permits really simple singletons to be used nearly anywhere.

template<class T> class singleton { public:   static T& Instance() {     static auto smart_ptr = LibSingleton::RequestInstance(       typeid(T).name(),       sizeof(T),       [](void* ptr){ return ::new( ptr ) T{}; },       [](void* ptr){ static_cast<T*>(ptr)->~T(); }     );     if (!smart_ptr)       exit(-1); // or throw something     return *static_cast<T*>(smart_ptr.get());   } protected:   singleton() = default;   ~singleton() = default; private:   singleton(singleton&&) = delete;   singleton& operator=(singleton&&) = delete; }; 

use looks like:

struct Logger : LibSingleton::singleton<Logger> {   friend class LibSingleton::singleton<Logger>;   void do_log( char const* sting ) {} private:   Logger() { /* ... */ } }; 
like image 30
Yakk - Adam Nevraumont Avatar answered Sep 26 '22 00:09

Yakk - Adam Nevraumont