zoukankan      html  css  js  c++  java
  • 从微观看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();
  • 相关阅读:
    js 立即调用函数
    layui confirm
    jquery ajax
    abap append 用法
    少年愁
    SAP 物料移动tcode
    常用tcode
    ME23N PO 打印预览 打印问题
    Y_TEXT001-(保存长文本)
    ZPPR001-(展bom)
  • 原文地址:https://www.cnblogs.com/kwliu/p/3115881.html
Copyright © 2011-2022 走看看