从微观看chrome 之一:Singleton<T> 范型类
Singleton是chrome中用来实现单列的一个范型类。chrome中大部分的与profile有关的服务都是用该类作为底层的实现。类定义的如下:
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_; };
Singleton范型可以给三个范型参数,分别是类型(Type),对Singleton定制的 辅助类型(traits),第三个不太懂,暂时不关注吧。
Singleton::get()实现对单列对象的获取,其中包含了对象的第一次访问时的创建,和线程安全的控制。
Singleton::OnExit() 用来控制单列对象的释放时机。
instance_是所持有的单例对象的指针。
所有这个成员都是private的,只能通过一个友元函数来访问,这个友元函数是friend Type* Type::GetInstance(), 也就是需要单列访问的类中的GetInstance方法。
Traits用来对Singleton<>进行一些配置化,提高Singleton<>的复用性。将DefaultSingletonTraits代码抄录如下:
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; };
可以看出Traits可以辅助 Singleton进行对象的创建,用定义的New和Delete函数来实现。然后剩下的 kRegisterAtExit成员变量用来进行控制程序退出时是否释放对象。除了DefaultSingletonTraits之外,还有LeakySingletonTraits 和StaticMemorySingletonTraits两个可选的traits.具体的功能大家可以看源码。
Singleton<T>::get的函数内容如下:
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对象。
如果一个对象需要进行单例访问,可以使用这个类,在对象定义时增加一个GetInstance的方法:
#include "base/memory/singleton.h" FooClass* FooClass::GetInstance() { return Singleton<FooClass>::get(); }
这样,需要访问这个对象的地方通过如下代码访问:
T::GetInstance()->Bar();