1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/ipc/chromium/src/base/lazy_instance.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,110 @@ 1.4 +// Copyright (c) 2008 The Chromium Authors. All rights reserved. 1.5 +// Use of this source code is governed by a BSD-style license that can be 1.6 +// found in the LICENSE file. 1.7 + 1.8 +// The LazyInstance<Type, Traits> class manages a single instance of Type, 1.9 +// which will be lazily created on the first time it's accessed. This class is 1.10 +// useful for places you would normally use a function-level static, but you 1.11 +// need to have guaranteed thread-safety. The Type constructor will only ever 1.12 +// be called once, even if two threads are racing to create the object. Get() 1.13 +// and Pointer() will always return the same, completely initialized instance. 1.14 +// When the instance is constructed it is registered with AtExitManager. The 1.15 +// destructor will be called on program exit. 1.16 +// 1.17 +// LazyInstance is completely thread safe, assuming that you create it safely. 1.18 +// The class was designed to be POD initialized, so it shouldn't require a 1.19 +// static constructor. It really only makes sense to declare a LazyInstance as 1.20 +// a global variable using the base::LinkerInitialized constructor. 1.21 +// 1.22 +// LazyInstance is similar to Singleton, except it does not have the singleton 1.23 +// property. You can have multiple LazyInstance's of the same type, and each 1.24 +// will manage a unique instance. It also preallocates the space for Type, as 1.25 +// to avoid allocating the Type instance on the heap. This may help with the 1.26 +// performance of creating the instance, and reducing heap fragmentation. This 1.27 +// requires that Type be a complete type so we can determine the size. 1.28 +// 1.29 +// Example usage: 1.30 +// static LazyInstance<MyClass> my_instance(base::LINKER_INITIALIZED); 1.31 +// void SomeMethod() { 1.32 +// my_instance.Get().SomeMethod(); // MyClass::SomeMethod() 1.33 +// 1.34 +// MyClass* ptr = my_instance.Pointer(); 1.35 +// ptr->DoDoDo(); // MyClass::DoDoDo 1.36 +// } 1.37 + 1.38 +#ifndef BASE_LAZY_INSTANCE_H_ 1.39 +#define BASE_LAZY_INSTANCE_H_ 1.40 + 1.41 +#include "base/atomicops.h" 1.42 +#include "base/basictypes.h" 1.43 + 1.44 +namespace base { 1.45 + 1.46 +template <typename Type> 1.47 +struct DefaultLazyInstanceTraits { 1.48 + static void New(void* instance) { 1.49 + // Use placement new to initialize our instance in our preallocated space. 1.50 + // The parenthesis is very important here to force POD type initialization. 1.51 + new (instance) Type(); 1.52 + } 1.53 + static void Delete(void* instance) { 1.54 + // Explicitly call the destructor. 1.55 + reinterpret_cast<Type*>(instance)->~Type(); 1.56 + } 1.57 +}; 1.58 + 1.59 +// We pull out some of the functionality into a non-templated base, so that we 1.60 +// can implement the more complicated pieces out of line in the .cc file. 1.61 +class LazyInstanceHelper { 1.62 + protected: 1.63 + enum { 1.64 + STATE_EMPTY = 0, 1.65 + STATE_CREATING = 1, 1.66 + STATE_CREATED = 2 1.67 + }; 1.68 + 1.69 + explicit LazyInstanceHelper(LinkerInitialized x) { /* state_ is 0 */ } 1.70 + // Declaring a destructor (even if it's empty) will cause MSVC to register a 1.71 + // static initializer to register the empty destructor with atexit(). 1.72 + 1.73 + // Make sure that instance is created, creating or waiting for it to be 1.74 + // created if neccessary. Constructs with |ctor| in the space provided by 1.75 + // |instance| and registers dtor for destruction at program exit. 1.76 + void EnsureInstance(void* instance, void (*ctor)(void*), void (*dtor)(void*)); 1.77 + 1.78 + base::subtle::Atomic32 state_; 1.79 + 1.80 + private: 1.81 + DISALLOW_COPY_AND_ASSIGN(LazyInstanceHelper); 1.82 +}; 1.83 + 1.84 +template <typename Type, typename Traits = DefaultLazyInstanceTraits<Type> > 1.85 +class LazyInstance : public LazyInstanceHelper { 1.86 + public: 1.87 + explicit LazyInstance(LinkerInitialized x) : LazyInstanceHelper(x) { } 1.88 + // Declaring a destructor (even if it's empty) will cause MSVC to register a 1.89 + // static initializer to register the empty destructor with atexit(). 1.90 + 1.91 + Type& Get() { 1.92 + return *Pointer(); 1.93 + } 1.94 + 1.95 + Type* Pointer() { 1.96 + Type* instance = reinterpret_cast<Type*>(&buf_); 1.97 + 1.98 + // We will hopefully have fast access when the instance is already created. 1.99 + if (base::subtle::NoBarrier_Load(&state_) != STATE_CREATED) 1.100 + EnsureInstance(instance, Traits::New, Traits::Delete); 1.101 + 1.102 + return instance; 1.103 + } 1.104 + 1.105 + private: 1.106 + int8_t buf_[sizeof(Type)]; // Preallocate the space for the Type instance. 1.107 + 1.108 + DISALLOW_COPY_AND_ASSIGN(LazyInstance); 1.109 +}; 1.110 + 1.111 +} // namespace base 1.112 + 1.113 +#endif // BASE_LAZY_INSTANCE_H_