Singleton

来源:互联网 发布:mac see sheer西柚色 编辑:程序博客网 时间:2024/05/01 13:36

 

// Default traits for Singleton<Type>. Calls operator new and operator delete on

// the object. Registers automatic deletion at process exit.

// Overload if you need arguments or another memory allocation function.

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;

};

 

 

// Alternate traits for use with the Singleton<Type>.  Identical to

// DefaultSingletonTraits except that the Singleton will not be cleaned up

// at exit.

template<typename Type>

struct LeakySingletonTraits : public DefaultSingletonTraits<Type> {

  static const bool kRegisterAtExit = false;

};

template <typename Type,
          typename Traits = DefaultSingletonTraits<Type>,
          typename DifferentiatingType = Type>
class Singleton {
 public:
  // This class is safe to be constructed and copy-constructed since it has no
  // member.
  // Return a pointer to the one true instance of the class.
  static Type* get() {
    // Our AtomicWord doubles as a spinlock, where a value of
    // kBeingCreatedMarker means the spinlock is being held for creation.
    static const base::subtle::AtomicWord kBeingCreatedMarker = 1;
    base::subtle::AtomicWord value = base::subtle::NoBarrier_Load(&instance_);
    if (value != 0 && value != 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,
                                             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();
      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 valid ptr.
    // Unless your constructor can be very time consuming, it is very unlikely
    // to hit this race.  When it does, we just spin and yield the thread until
    // the object has been created.
    while (true) {
      value = base::subtle::NoBarrier_Load(&instance_);
      if (value != kBeingCreatedMarker)
        break;
      PlatformThread::YieldCurrentThread();
    }
    return reinterpret_cast<Type*>(value);
  }
  // Shortcuts.
  Type& operator*() {
    return *get();
  }
  Type* operator->() {
    return get();
  }
 private:
  // Adapter function for use with AtExit().  This should be called single
  // threaded, but we might as well take the precautions anyway.
  static void OnExit(void* unused) {
    // AtExit should only ever be register after 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::AtomicWord instance_;
};
template <typename Type, typename Traits, typename DifferentiatingType>
base::subtle::AtomicWord Singleton<Type, Traits, DifferentiatingType>::
    instance_ = 0;

 

原创粉丝点击