// 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.
// Allocates the object.
// initialization.
// Destroys the object.
// exit. See below for the required call that makes this happen.
// Alternate traits for use with the Singleton<Type>. Identical to
// at exit.
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;