Singleton

Apollo Singleton Macro

  #ifndef CYBER_COMMON_MACROS_H_
  #define CYBER_COMMON_MACROS_H_

  #include <iostream>
  #include <memory>
  #include <mutex>
  #include <type_traits>
  #include <utility>

  #include "cyber/base/macros.h"

  DEFINE_TYPE_TRAIT(HasShutdown, Shutdown)

  template <typename T>
  typename std::enable_if<HasShutdown<T>::value>::type CallShutdown(T *instance) {
    instance->Shutdown();
  }

  template <typename T>
  typename std::enable_if<!HasShutdown<T>::value>::type CallShutdown(
      T *instance) {
    (void)instance;
  }

  // There must be many copy-paste versions of these macros which are same
  // things, undefine them to avoid conflict.
  #undef UNUSED
  #undef DISALLOW_COPY_AND_ASSIGN

  #define UNUSED(param) (void)param

  #define DISALLOW_COPY_AND_ASSIGN(classname) \
    classname(const classname &) = delete;    \
    classname &operator=(const classname &) = delete;

  #define DECLARE_SINGLETON(classname)                                      \
  public:                                                                  \
    static classname *Instance(bool create_if_needed = true) {              \
      static classname *instance = nullptr;                                 \
      if (!instance && create_if_needed) {                                  \
        static std::once_flag flag;                                         \
        std::call_once(flag,                                                \
                      [&] { instance = new (std::nothrow) classname(); }); \
      }                                                                     \
      return instance;                                                      \
    }                                                                       \
                                                                            \
    static void CleanUp() {                                                 \
      auto instance = Instance(false);                                      \
      if (instance != nullptr) {                                            \
        CallShutdown(instance);                                             \
      }                                                                     \
    }                                                                       \
                                                                            \
  private:                                                                 \
    classname();                                                            \
    DISALLOW_COPY_AND_ASSIGN(classname)

  #endif  // CYBER_COMMON_MACROS_H_

细节分析

  • 为了能够让程序员显式的禁用某个函数,C++11 标准引入了一个新特性:”=delete”函数。程序员只需在函数声明后上“=delete;”,就可将该函数禁用。
    class X3
    {
    public:
        X3();
        X3(const X3&) = delete;  // 声明拷贝构造函数为 deleted 函数
        X3& operator = (const X3 &) = delete; // 声明拷贝赋值操作符为 deleted 函数
    };
    
  • 在多线程编程中,有一个常见的情景是某个任务只需要执行一次。在C++11中提供了很方便的辅助类once_flag,call_once。
    #include <iostream>
    #include <thread>
    #include <mutex>
      
    std::once_flag flag;
      
    void do_once() {
        //也可以写在这里。要记住static,一旦flag被销毁了就不能保证只执行一次了
        //static std::once_flag flag;
        std::call_once(flag, [](){ std::cout << "Called once" << std::endl; });
    }
      
    int main() {
        std::thread t1(do_once);
        std::thread t2(do_once);
        std::thread t3(do_once);
        std::thread t4(do_once);
      
        t1.join();
        t2.join();
        t3.join();
        t4.join();
    }
    //可以看到,只会输出一行Called once
    

Search

    欢迎添加我的微信

    闷骚的程序员

    Table of Contents