ipc/chromium/src/base/singleton.h

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
     2 // Use of this source code is governed by a BSD-style license that can be
     3 // found in the LICENSE file.
     5 #ifndef BASE_SINGLETON_H_
     6 #define BASE_SINGLETON_H_
     8 #include "base/at_exit.h"
     9 #include "base/atomicops.h"
    10 #include "base/platform_thread.h"
    12 // Default traits for Singleton<Type>. Calls operator new and operator delete on
    13 // the object. Registers automatic deletion at process exit.
    14 // Overload if you need arguments or another memory allocation function.
    15 template<typename Type>
    16 struct DefaultSingletonTraits {
    17   // Allocates the object.
    18   static Type* New() {
    19     // The parenthesis is very important here; it forces POD type
    20     // initialization.
    21     return new Type();
    22   }
    24   // Destroys the object.
    25   static void Delete(Type* x) {
    26     delete x;
    27   }
    29   // Set to true to automatically register deletion of the object on process
    30   // exit. See below for the required call that makes this happen.
    31   static const bool kRegisterAtExit = true;
    32 };
    35 // Alternate traits for use with the Singleton<Type>.  Identical to
    36 // DefaultSingletonTraits except that the Singleton will not be cleaned up
    37 // at exit.
    38 template<typename Type>
    39 struct LeakySingletonTraits : public DefaultSingletonTraits<Type> {
    40   static const bool kRegisterAtExit = false;
    41 };
    44 // The Singleton<Type, Traits, DifferentiatingType> class manages a single
    45 // instance of Type which will be created on first use and will be destroyed at
    46 // normal process exit). The Trait::Delete function will not be called on
    47 // abnormal process exit.
    48 //
    49 // DifferentiatingType is used as a key to differentiate two different
    50 // singletons having the same memory allocation functions but serving a
    51 // different purpose. This is mainly used for Locks serving different purposes.
    52 //
    53 // Example usages: (none are preferred, they all result in the same code)
    54 //   1. FooClass* ptr = Singleton<FooClass>::get();
    55 //      ptr->Bar();
    56 //   2. Singleton<FooClass>()->Bar();
    57 //   3. Singleton<FooClass>::get()->Bar();
    58 //
    59 // Singleton<> has no non-static members and doesn't need to actually be
    60 // instantiated. It does no harm to instantiate it and use it as a class member
    61 // or at global level since it is acting as a POD type.
    62 //
    63 // This class is itself thread-safe. The underlying Type must of course be
    64 // thread-safe if you want to use it concurrently. Two parameters may be tuned
    65 // depending on the user's requirements.
    66 //
    67 // Glossary:
    68 //   RAE = kRegisterAtExit
    69 //
    70 // On every platform, if Traits::RAE is true, the singleton will be destroyed at
    71 // process exit. More precisely it uses base::AtExitManager which requires an
    72 // object of this type to be instanciated. AtExitManager mimics the semantics
    73 // of atexit() such as LIFO order but under Windows is safer to call. For more
    74 // information see at_exit.h.
    75 //
    76 // If Traits::RAE is false, the singleton will not be freed at process exit,
    77 // thus the singleton will be leaked if it is ever accessed. Traits::RAE
    78 // shouldn't be false unless absolutely necessary. Remember that the heap where
    79 // the object is allocated may be destroyed by the CRT anyway.
    80 //
    81 // If you want to ensure that your class can only exist as a singleton, make
    82 // its constructors private, and make DefaultSingletonTraits<> a friend:
    83 //
    84 //   #include "base/singleton.h"
    85 //   class FooClass {
    86 //    public:
    87 //     void Bar() { ... }
    88 //    private:
    89 //     FooClass() { ... }
    90 //     friend struct DefaultSingletonTraits<FooClass>;
    91 //
    92 //     DISALLOW_EVIL_CONSTRUCTORS(FooClass);
    93 //   };
    94 //
    95 // Caveats:
    96 // (a) Every call to get(), operator->() and operator*() incurs some overhead
    97 //     (16ns on my P4/2.8GHz) to check whether the object has already been
    98 //     initialized.  You may wish to cache the result of get(); it will not
    99 //     change.
   100 //
   101 // (b) Your factory function must never throw an exception. This class is not
   102 //     exception-safe.
   103 //
   104 template <typename Type,
   105           typename Traits = DefaultSingletonTraits<Type>,
   106           typename DifferentiatingType = Type>
   107 class Singleton {
   108  public:
   109   // This class is safe to be constructed and copy-constructed since it has no
   110   // member.
   112   // Return a pointer to the one true instance of the class.
   113   static Type* get() {
   114     // Our AtomicWord doubles as a spinlock, where a value of
   115     // kBeingCreatedMarker means the spinlock is being held for creation.
   116     static const base::subtle::AtomicWord kBeingCreatedMarker = 1;
   118     base::subtle::AtomicWord value = base::subtle::NoBarrier_Load(&instance_);
   119     if (value != 0 && value != kBeingCreatedMarker)
   120       return reinterpret_cast<Type*>(value);
   122     // Object isn't created yet, maybe we will get to create it, let's try...
   123     if (base::subtle::Acquire_CompareAndSwap(&instance_,
   124                                              0,
   125                                              kBeingCreatedMarker) == 0) {
   126       // instance_ was NULL and is now kBeingCreatedMarker.  Only one thread
   127       // will ever get here.  Threads might be spinning on us, and they will
   128       // stop right after we do this store.
   129       Type* newval = Traits::New();
   130       base::subtle::Release_Store(
   131           &instance_, reinterpret_cast<base::subtle::AtomicWord>(newval));
   133       if (Traits::kRegisterAtExit)
   134         base::AtExitManager::RegisterCallback(OnExit, NULL);
   136       return newval;
   137     }
   139     // We hit a race.  Another thread beat us and either:
   140     // - Has the object in BeingCreated state
   141     // - Already has the object created...
   142     // We know value != NULL.  It could be kBeingCreatedMarker, or a valid ptr.
   143     // Unless your constructor can be very time consuming, it is very unlikely
   144     // to hit this race.  When it does, we just spin and yield the thread until
   145     // the object has been created.
   146     while (true) {
   147       value = base::subtle::NoBarrier_Load(&instance_);
   148       if (value != kBeingCreatedMarker)
   149         break;
   150       PlatformThread::YieldCurrentThread();
   151     }
   153     return reinterpret_cast<Type*>(value);
   154   }
   156   // Shortcuts.
   157   Type& operator*() {
   158     return *get();
   159   }
   161   Type* operator->() {
   162     return get();
   163   }
   165  private:
   166   // Adapter function for use with AtExit().  This should be called single
   167   // threaded, but we might as well take the precautions anyway.
   168   static void OnExit(void* unused) {
   169     // AtExit should only ever be register after the singleton instance was
   170     // created.  We should only ever get here with a valid instance_ pointer.
   171     Traits::Delete(reinterpret_cast<Type*>(
   172         base::subtle::NoBarrier_AtomicExchange(&instance_, 0)));
   173   }
   174   static base::subtle::AtomicWord instance_;
   175 };
   177 template <typename Type, typename Traits, typename DifferentiatingType>
   178 base::subtle::AtomicWord Singleton<Type, Traits, DifferentiatingType>::
   179     instance_ = 0;
   181 #endif  // BASE_SINGLETON_H_

mercurial