blob: c6a1685f4c9676c9bf953b11254c533b7a822331 [file] [log] [blame]
license.botbf09a502008-08-24 00:55:551// 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.
initial.commitd7cae122008-07-26 21:49:384
[email protected]9795ec12008-09-08 09:06:515#ifndef BASE_SINGLETON_H_
6#define BASE_SINGLETON_H_
initial.commitd7cae122008-07-26 21:49:387
[email protected]ae6454712008-08-01 03:06:258#include "base/at_exit.h"
[email protected]156f8072008-08-06 11:19:429#include "base/atomicops.h"
10#include "base/platform_thread.h"
initial.commitd7cae122008-07-26 21:49:3811
12// Default traits for Singleton<Type>. Calls operator new and operator delete on
[email protected]ae6454712008-08-01 03:06:2513// the object. Registers automatic deletion at process exit.
initial.commitd7cae122008-07-26 21:49:3814// Overload if you need arguments or another memory allocation function.
15template<typename Type>
16struct 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 }
23
24 // Destroys the object.
25 static void Delete(Type* x) {
26 delete x;
27 }
28
[email protected]ae6454712008-08-01 03:06:2529 // Set to true to automatically register deletion of the object on process
30 // exit. See below for the required call that makes this happen.
initial.commitd7cae122008-07-26 21:49:3831 static const bool kRegisterAtExit = true;
initial.commitd7cae122008-07-26 21:49:3832};
33
initial.commitd7cae122008-07-26 21:49:3834// The Singleton<Type, Traits, DifferentiatingType> class manages a single
35// instance of Type which will be created on first use and will be destroyed at
[email protected]ae6454712008-08-01 03:06:2536// normal process exit). The Trait::Delete function will not be called on
37// abnormal process exit.
initial.commitd7cae122008-07-26 21:49:3838//
39// DifferentiatingType is used as a key to differentiate two different
40// singletons having the same memory allocation functions but serving a
41// different purpose. This is mainly used for Locks serving different purposes.
42//
43// Example usages: (none are preferred, they all result in the same code)
44// 1. FooClass* ptr = Singleton<FooClass>::get();
45// ptr->Bar();
46// 2. Singleton<FooClass>()->Bar();
47// 3. Singleton<FooClass>::get()->Bar();
48//
49// Singleton<> has no non-static members and doesn't need to actually be
50// instantiated. It does no harm to instantiate it and use it as a class member
51// or at global level since it is acting as a POD type.
52//
53// This class is itself thread-safe. The underlying Type must of course be
54// thread-safe if you want to use it concurrently. Two parameters may be tuned
55// depending on the user's requirements.
56//
57// Glossary:
initial.commitd7cae122008-07-26 21:49:3858// RAE = kRegisterAtExit
59//
60// On every platform, if Traits::RAE is true, the singleton will be destroyed at
[email protected]ae6454712008-08-01 03:06:2561// process exit. More precisely it uses base::AtExitManager which requires an
62// object of this type to be instanciated. AtExitManager mimics the semantics
63// of atexit() such as LIFO order but under Windows is safer to call. For more
64// information see at_exit.h.
65//
66// If Traits::RAE is false, the singleton will not be freed at process exit,
67// thus the singleton will be leaked if it is ever accessed. Traits::RAE
68// shouldn't be false unless absolutely necessary. Remember that the heap where
69// the object is allocated may be destroyed by the CRT anyway.
initial.commitd7cae122008-07-26 21:49:3870//
initial.commitd7cae122008-07-26 21:49:3871// If you want to ensure that your class can only exist as a singleton, make
72// its constructors private, and make DefaultSingletonTraits<> a friend:
73//
74// #include "base/singleton.h"
75// class FooClass {
76// public:
77// void Bar() { ... }
78// private:
79// FooClass() { ... }
[email protected]e0edf60e2008-08-19 17:52:1880// friend struct DefaultSingletonTraits<FooClass>;
initial.commitd7cae122008-07-26 21:49:3881//
82// DISALLOW_EVIL_CONSTRUCTORS(FooClass);
83// };
84//
85// Caveats:
86// (a) Every call to get(), operator->() and operator*() incurs some overhead
87// (16ns on my P4/2.8GHz) to check whether the object has already been
88// initialized. You may wish to cache the result of get(); it will not
89// change.
90//
91// (b) Your factory function must never throw an exception. This class is not
92// exception-safe.
93//
initial.commitd7cae122008-07-26 21:49:3894template <typename Type,
95 typename Traits = DefaultSingletonTraits<Type>,
96 typename DifferentiatingType = Type>
[email protected]156f8072008-08-06 11:19:4297class Singleton {
initial.commitd7cae122008-07-26 21:49:3898 public:
99 // This class is safe to be constructed and copy-constructed since it has no
100 // member.
101
102 // Return a pointer to the one true instance of the class.
103 static Type* get() {
[email protected]156f8072008-08-06 11:19:42104 // Our AtomicWord doubles as a spinlock, where a value of
105 // kBeingCreatedMarker means the spinlock is being held for creation.
106 static const base::subtle::AtomicWord kBeingCreatedMarker = 1;
initial.commitd7cae122008-07-26 21:49:38107
[email protected]156f8072008-08-06 11:19:42108 base::subtle::AtomicWord value = base::subtle::NoBarrier_Load(&instance_);
109 if (value != 0 && value != kBeingCreatedMarker)
110 return reinterpret_cast<Type*>(value);
111
112 // Object isn't created yet, maybe we will get to create it, let's try...
113 if (base::subtle::Acquire_CompareAndSwap(&instance_,
114 0,
115 kBeingCreatedMarker) == 0) {
116 // instance_ was NULL and is now kBeingCreatedMarker. Only one thread
117 // will ever get here. Threads might be spinning on us, and they will
118 // stop right after we do this store.
119 Type* newval = Traits::New();
120 base::subtle::Release_Store(
121 &instance_, reinterpret_cast<base::subtle::AtomicWord>(newval));
122
123 if (Traits::kRegisterAtExit)
[email protected]9795ec12008-09-08 09:06:51124 base::AtExitManager::RegisterCallback(OnExit, NULL);
[email protected]156f8072008-08-06 11:19:42125
126 return newval;
127 }
128
129 // We hit a race. Another thread beat us and either:
130 // - Has the object in BeingCreated state
131 // - Already has the object created...
132 // We know value != NULL. It could be kBeingCreatedMarker, or a valid ptr.
133 // Unless your constructor can be very time consuming, it is very unlikely
134 // to hit this race. When it does, we just spin and yield the thread until
135 // the object has been created.
136 while (true) {
137 value = base::subtle::NoBarrier_Load(&instance_);
138 if (value != kBeingCreatedMarker)
139 break;
140 PlatformThread::YieldCurrentThread();
141 }
142
143 return reinterpret_cast<Type*>(value);
initial.commitd7cae122008-07-26 21:49:38144 }
145
146 // Shortcuts.
147 Type& operator*() {
148 return *get();
149 }
150
151 Type* operator->() {
152 return get();
153 }
154
155 private:
[email protected]156f8072008-08-06 11:19:42156 // Adapter function for use with AtExit(). This should be called single
157 // threaded, but we might as well take the precautions anyway.
[email protected]9795ec12008-09-08 09:06:51158 static void OnExit(void* unused) {
[email protected]156f8072008-08-06 11:19:42159 // AtExit should only ever be register after the singleton instance was
160 // created. We should only ever get here with a valid instance_ pointer.
[email protected]b321afd72008-08-11 08:33:13161 Traits::Delete(reinterpret_cast<Type*>(
162 base::subtle::NoBarrier_AtomicExchange(&instance_, 0)));
initial.commitd7cae122008-07-26 21:49:38163 }
[email protected]156f8072008-08-06 11:19:42164 static base::subtle::AtomicWord instance_;
initial.commitd7cae122008-07-26 21:49:38165};
166
initial.commitd7cae122008-07-26 21:49:38167template <typename Type, typename Traits, typename DifferentiatingType>
[email protected]156f8072008-08-06 11:19:42168base::subtle::AtomicWord Singleton<Type, Traits, DifferentiatingType>::
[email protected]45d69a22008-08-07 12:21:23169 instance_ = 0;
initial.commitd7cae122008-07-26 21:49:38170
[email protected]9795ec12008-09-08 09:06:51171#endif // BASE_SINGLETON_H_