Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

c++ singleton implementation Meyer's vs call_once

Well, i'm using singleton in my own project. The most frequently used singleton implementation might be Meyer's singletion and that of using std::call_once or pthread_once. Both of them are thread safe for parallelized computing

//Meyer's singleton
class MySingleton{
public:
  static MySingleton& getInstance(){
    static MySingleton instance;
    // volatile int dummy{};
    return instance;
  }
private:
  MySingleton()= default;
  ~MySingleton()= default;
  MySingleton(const MySingleton&)= delete;
  MySingleton& operator=(const MySingleton&)= delete;

};


//with call_once
class MySingleton{
public:
  static MySingleton& getInstance(){
    std::call_once(initInstanceFlag, &MySingleton::initSingleton);
    // volatile int dummy{};
    return *instance;
  }
private:
  MySingleton()= default;
  ~MySingleton()= default;
  MySingleton(const MySingleton&)= delete;
  MySingleton& operator=(const MySingleton&)= delete;

  static MySingleton* instance;
  static std::once_flag initInstanceFlag;

  static void initSingleton(){
    instance= new MySingleton;
  }
};

MySingleton* MySingleton::instance= nullptr;
std::once_flag MySingleton::initInstanceFlag;

Meyer's implimentation using local static variable to ensure thread safety and return the instance identity, while the latter one achieved by call_once and reture a pointer. In my experiment, the Meyer's implimentation sames a little bit faster. But most project using the call_once approach for the most basic singleton implimentation, althought some small component of the project using Meyer's implimentation. I just wondering is there any principle to follow, and what's the pros and cons of this two different implimentation?

like image 742
Weijian Sun Avatar asked Oct 11 '19 07:10

Weijian Sun


1 Answers

The call_once version keeps a pointer to the instance and create it using new. Since no delete is ever called on the pointer, this solution poses some troubles if one needs sensible code to be run in the instance destructor. Apart from the annoying dangling pointer at process exit, one can consider using it if the instance destructor is just a default one like in your example.

like image 60
p-a-o-l-o Avatar answered Nov 09 '22 13:11

p-a-o-l-o