从微观看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();

 

 

 

 

 

 

 

 

 

 

 

 

 

 

posted on 2013-06-03 17:55  一颗麦粒  阅读(2480)  评论(2编辑  收藏  举报

导航