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.

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

mercurial