c11 generic singleton

1 篇文章 0 订阅
1 篇文章 0 订阅

单例模式保证该类对象只创建一个,且提供全局唯一的访问点。具体实现而言,主要有三个问题:对象初始化,访问和销毁。

对象初始化。常见的初始化形式有四种:静态对象成员,静态指针成员,静态本地对象,静态本地指针。对象成员在main函数之前就已经初始化了,不能使用任何系统启动才加载的配置项;而指针成员同理,但可以实现延迟实例化。这两种形式在多线程情况下,都需要加锁进行实例化(从语法上,静态成员对象能保证对象唯一性吗?),从而防止产生多个副本。对于本地变量,在第一次访问该静态方法时,进行初始化,要求该对象必须是is_default_constructible,且c11从语法上保证其并发情况的下的唯一性。而对于本地指针,则可以进行定制化的初始化,但同时也要求通过锁进行并发控制,反之创建多个副本。因此本地对象优于成员对象,因为有并发保证,而且可以延迟初始化;而当对象初始化和访问在不同的方式里面时,指针成员优于本地变量,因为静态本地变量不能提供跨方法访问。所以,初始化代码如下:

// default constructible type
Tp& Instance() { static Tp s_instance;   return s_instance;}   
// non-default constructible type
template<class... Args>                                                        
Tp& Instance(Args&& args...) { 
       std::call_once( s_init_once_flag, [&](){ 
                               s_pInstance = std::unique_ptr<Tp>(new Tp(std::forward<Args>(args)...)); }  );  
       return *s_pInstance;
}

对象访问。对于default constructible type,自然通过Instance()访问;而对于non-default constructible type既可以通过初始化的Instance(args...)也可以通过Instance()来访问。

对象销毁。对于default constructible type,系统exit的时候会自动销毁静态本地变量;对于non-default constructible type则由unique_ptr来保证销毁。

    template
   
   
    
    
    class Singleton : public Noncopyable
    {
        public:
            static Tp& Instance()
            {
                // 1>c11 guarantees that a local static variable is only run once
                // this ensures thread-safety in initializing singletion class
                // in concurrecy context
                // 2>it won't init unless it's first accessed
                // 3>if g_instance works as a static member variable
                // it will be inited before main, which means
                // its initialization can't take advantage of
                // info known only once the program is up and running
                // ### it's unnecessary to be zero-argument default constructed
                // ### it should support various constructor
                static Tp s_instance;

                return s_instance;
            }

            // noncopyable
//          Singleton
    
    
     
     & operator=( const Singleton
     
     
      
      & ) = delete;
//          Singleton( const Singleton
      
      
       
       &) = delete;

        protected:
            // if a class supports singleton, it has to inherit class Singleton
            Singleton(){};
            virtual ~Singleton(){};
    };

    template
       
       
         class Singleton 
        
          : public Noncopyable { public: template 
         
           static Tp& Instance(Args&&... args) { std::call_once( s_inited_once_flag, [&](){ s_pInstance = std::unique_ptr 
          
            ( new Tp(std::forward 
           
             (args)... ) ); // std::atexit(destroy); }); return *s_pInstance; } static Tp& Instance() { if( nullptr == s_pInstance ) { throw std::logic_error(std::string() + typeid(Tp).name() + " is not inited!\n"); } return *s_pInstance; } // noncopyable // Singleton 
            
              & operator=( const Singleton 
             
               & ) = delete; // Singleton( const Singleton 
              
                &) = delete; protected: // if a class supports singleton, it has to inherit class Singleton Singleton(){}; virtual ~Singleton(){}; private: static std::unique_ptr 
               
                 s_pInstance; static std::once_flag s_inited_once_flag; /* static void destroy() { if( nullptr != s_pInstance ) { delete s_pInstance; s_pInstance = nullptr; std::cout << typeid(Tp).name() << " get deleted in " << __PRETTY_FUNCTION__ << '\n'; } } */ }; template 
                
                  std::unique_ptr 
                 
                   Singleton 
                  
                    ::s_pInstance; template 
                   
                     std::once_flag Singleton 
                    
                      ::s_inited_once_flag; 
                     
                    
                   
                  
                 
                
               
              
             
            
           
          
         
       
      
      
     
     
    
    
   
   

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值