Skip to content

Instantly share code, notes, and snippets.

@qiaohaijun
Last active June 13, 2017 11:56
Show Gist options
  • Save qiaohaijun/b4f9bdea321dfd8b57b44bb0d80a745e to your computer and use it in GitHub Desktop.
Save qiaohaijun/b4f9bdea321dfd8b57b44bb0d80a745e to your computer and use it in GitHub Desktop.
template <typename Type,
          typename Traits = DefaultSingletonTraits<Type>,
          typename DifferentiatingType = Type>
class Singleton {
 private:
  // Classes using the Singleton<T> pattern should declare a GetInstance()
  // method and call Singleton::get() from within that.
  friend Type* Type::GetInstance();

  // Return a pointer to the one true instance of the class.
  static Type* get() // Adapter function for use with AtExit().  This should be called single
  // threaded, so don't use atomic operations.
  // Calling OnExit while singleton is in use by other threads is a mistake.
  static void OnExit(void* /*unused*/) 
static base::subtle::AtomicWord instance_;
};

这段代码有三个泛型参数

  1. Type
  2. traits
  3. DifferentiatingType

有如下几个函数

  1. get()
  2. onExit() 所有的函数都是private的,只能通过一个友元函数来访问。
template<typename Type>
struct DefaultSingletonTraits {
  // Allocates the object.
  static Type* New() {
    // The parenthesis is very important here; it forces POD type
    // initialization.
    return new Type();
  }

  // Destroys the object.
  static void Delete(Type* x) {
    delete x;
  }

  // Set to true to automatically register deletion of the object on process
  // exit. See below for the required call that makes this happen.
  static const bool kRegisterAtExit = true;

  // Set to false to disallow access on a non-joinable thread.  This is
  // different from kRegisterAtExit because StaticMemorySingletonTraits allows
  // access on non-joinable threads, and gracefully handles this.
  static const bool kAllowedToAccessOnNonjoinableThread = false;
};

c++ 的泛型编程,确实有一些细节需要好好思考。像编译器一样。

可以看出Traits可以辅助 Singleton进行对象的创建,用定义的New和Delete函数来实现。然后剩下的 kRegisterAtExit成员变量用来进行控制程序退出时是否释放对象。除了DefaultSingletonTraits之外,还有LeakySingletonTraits 和StaticMemorySingletonTraits两个可选的traits.具体的功能大家可以看源码。

static Type* get() {
    base::subtle::AtomicWord value = base::subtle::NoBarrier_Load(&instance_);
    if (value != 0 && value != base::internal::kBeingCreatedMarker) {
return reinterpret_cast<Type*>(value);
    }

    // Object isn't created yet, maybe we will get to create it, let's try...
    if (base::subtle::Acquire_CompareAndSwap(
          &instance_, 0, base::internal::kBeingCreatedMarker) == 0) {
      // instance_ was NULL and is now kBeingCreatedMarker.  Only one thread
      // will ever get here.  Threads might be spinning on us, and they will
      // stop right after we do this store.
      Type* newval = Traits::New();

      // This annotation helps race detectors recognize correct lock-less
      // synchronization between different threads calling get().
base::subtle::Release_Store(
          &instance_, reinterpret_cast<base::subtle::AtomicWord>(newval));

      if (newval != NULL && Traits::kRegisterAtExit)
        base::AtExitManager::RegisterCallback(OnExit, NULL);

      return newval;
    }

    // We hit a race. Wait for the other thread to complete it.
    value = base::internal::WaitForInstance(&instance_);
return reinterpret_cast<Type*>(value);
  }
  

代码会先尝试获取一次对象,如果没有获取到,判断是否创建了,如果没有创建,则使用Traits::New方法来进行创建,否则说明有其他人正在访问这个Singleton对象,等待该Singleton对象。

#include "base/memory/singleton.h"
FooClass* FooClass::GetInstance() {
    return Singleton<FooClass>::get();
}

这个singleton的代码很通用啊。

@qiaohaijun
Copy link
Author

问题

  1. typename

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment