对比Chrome 中的单例模式和公司中的单例模式体会到google代码的优雅

来源:互联网 发布:eclipse编译java 编辑:程序博客网 时间:2024/04/28 10:16

自己的代码

 

template<classT>

class CSingle

{

public:

    CSingle (void){}

    virtual ~ CSingle (void){}

 

    static T* GetInstance()

    {

       static T s_Instance;

       return &s_Instance;

    }

};

 

 

将Chrome 中的singleton.h代码贴上

 

template<typename Type,

          typename Traits =DefaultSingletonTraits<Type>,

          typename DifferentiatingType =Type>

classSingleton {

 public:

  // This class is safe to be constructed andcopy-constructed since it has no

  // member.

 

  // Return a pointer to the one true instanceof the class.

  static Type* get() {

    // Our AtomicWord doubles as a spinlock,where a value of

    // kBeingCreatedMarker means the spinlockis being held for creation.

    static const base::subtle::AtomicWordkBeingCreatedMarker = 1;

 

    base::subtle::AtomicWordvalue =base::subtle::NoBarrier_Load(&instance_);

    if (value != 0 &&value!= kBeingCreatedMarker) {

      // See the corresponding HAPPENS_BEFOREbelow.

      ANNOTATE_HAPPENS_AFTER(&instance_);

      return reinterpret_cast<Type*>(value);

    }

 

    // Object isn't created yet, maybe we willget to create it, let's try...

    if (base::subtle::Acquire_CompareAndSwap(&instance_,

                                             0,

                                             kBeingCreatedMarker)== 0) {

      // instance_ was NULL and is nowkBeingCreatedMarker.  Only one thread

      // will ever get here.  Threads might be spinning on us, and theywill

      // stop right after we do this store.

      Type*newval =Traits::New();

 

      // This annotation helps race detectorsrecognize correct lock-less

      // synchronization between differentthreads calling get().

      // See the corresponding HAPPENS_AFTERbelow and above.

      ANNOTATE_HAPPENS_BEFORE(&instance_);

      base::subtle::Release_Store(

          &instance_, reinterpret_cast<base::subtle::AtomicWord>(newval));

 

      if (Traits::kRegisterAtExit)

        base::AtExitManager::RegisterCallback(OnExit,NULL);

 

      return newval;

    }

 

    // We hit a race.  Another thread beat us and either:

    // - Has the object in BeingCreated state

    // - Already has the object created...

    // We know value != NULL.  It could be kBeingCreatedMarker, or a validptr.

    // Unless your constructor can be very timeconsuming, it is very unlikely

    // to hit this race.  When it does, we just spin and yield thethread until

    // the object has been created.

    while (true) {

      value = base::subtle::NoBarrier_Load(&instance_);

      if (value !=kBeingCreatedMarker)

        break;

      PlatformThread::YieldCurrentThread();

    }

 

    // See the corresponding HAPPENS_BEFOREabove.

    ANNOTATE_HAPPENS_AFTER(&instance_);

    return reinterpret_cast<Type*>(value);

  }

 

  // Shortcuts.

  Type& operator*() {

    return *get();

  }

 

  Type* operator->() {

    return get();

  }

 

 private:

  // Adapter function for use withAtExit().  This should be called single

  // threaded, but we might as well take theprecautions anyway.

  static void OnExit(void*unused){

    // AtExit should only ever be registerafter the singleton instance was

    // created. We should only ever get here with a valid instance_ pointer.

    Traits::Delete(reinterpret_cast<Type*>(

        base::subtle::NoBarrier_AtomicExchange(&instance_,0)));

  }

  static base::subtle::AtomicWordinstance_;

};

 

template<typename Type, typenameTraits, typename DifferentiatingType>

base::subtle::AtomicWord Singleton<Type,Traits,DifferentiatingType>::

    instance_ = 0;

 

#endif  // BASE_SINGLETON_H_

 

如果需要使某个类单例,则从

Template<classT>

Class CA: CSingle <T>

{

}

使用的时候

CA:: GetInstance()能得到单一实例,产生的对象在PE文件的BSS区,想要将对象从内存中释放掉不是很自由。而析构的时候,在WinMain 函数退出之后才调用,但是调用的顺序很混乱。如果对象之间的有依赖关系,那么在程序结束的时候就会出现问题。解决的方法很土,使用TerminateProcess 结束。

而Chrome 中单例使用

CA*p = Singleton<CA>::get();

产生的对象在堆中,以后可以自由的删除,可以很好的控制对象的生命周期。

 

而且产生单例的方法是,如果你想支持单例模式就要从CSingleInstanceBase派生,是紧耦合的方式,代码量增大,而且不优雅。而google的解决方法是类似函数调用的方式 调用完成之后产生一个静态指针,下次就使用上次的指针。优雅的解决得方式 。

在释放指针的时候,将指针重新清0

 

Google 处理方式考虑了:

1 堆中申请

2 可以自由释放

3 可以重复申请

4 线程安全

5 get函数可以重入

 

CSingle 中申请的时候,

1 未使用堆申请

2 不能够简单释放

3 不能重复申请

4 不是线程安全

 

还曾看过如下代码:

template<typename TYPE >TYPE* CSingletonT<TYPE>::getInstance()

{

    if( m_pInstance ==NULL )

    {

       CComCritSecLock<CComCriticalSection>guard(GetUtilGlobalMutex() );

       if( m_pInstance ==NULL )

       {

           m_pInstance = newTYPE();

       }

    }

    return m_pInstance;

}

使用了一个全局的CRITICAL_SECTION,效率上要比 InterlockedExchangePointer效率低下,而且所有的申请对象都是用一个对象来抑制竞争关系,而竞争关系只有在同一个对象申请的时候才应该加锁,所以这个代码也是有问题的。

 


原创粉丝点击