summaryrefslogtreecommitdiffstats
path: root/base/lazy_instance.h
diff options
context:
space:
mode:
authordeanm@google.com <deanm@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2008-09-08 14:11:13 +0000
committerdeanm@google.com <deanm@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2008-09-08 14:11:13 +0000
commit30039e6ec600f1ac2a34e0881f4c0c10ee6f80cd (patch)
tree081d130207172ab523ea08bb591f0fee9a369f30 /base/lazy_instance.h
parentfbcfafe4cd6d4f69ad0e1e3d921fb05bb5fcadfd (diff)
downloadchromium_src-30039e6ec600f1ac2a34e0881f4c0c10ee6f80cd.zip
chromium_src-30039e6ec600f1ac2a34e0881f4c0c10ee6f80cd.tar.gz
chromium_src-30039e6ec600f1ac2a34e0881f4c0c10ee6f80cd.tar.bz2
Create a LazyInstance abstraction for avoiding static constructors by lazily creating an instance of an object on first access. This is like Singleton, but without the Singleton property of sharing instances. This also preallocates space for the object to avoid the heap to try to help fragmentation and creation performance.
Review URL: http://codereview.chromium.org/1608 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@1837 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base/lazy_instance.h')
-rw-r--r--base/lazy_instance.h105
1 files changed, 105 insertions, 0 deletions
diff --git a/base/lazy_instance.h b/base/lazy_instance.h
new file mode 100644
index 0000000..5be41bd
--- /dev/null
+++ b/base/lazy_instance.h
@@ -0,0 +1,105 @@
+// Copyright (c) 2008 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// The LazyInstance<Type, Traits> class manages a single instance of Type,
+// which will be lazily created on the first time it's accessed. This class is
+// useful for places you would normally use a function-level static, but you
+// need to have guaranteed thread-safety. The Type constructor will only ever
+// be called once, even if two threads are racing to create the object. Get()
+// and Pointer() will always return the same, completely initialized instance.
+// When the instance is constructed it is registered with AtExitManager. The
+// destructor will be called on program exit.
+//
+// LazyInstance is completely thread safe, assuming that you create it safely.
+// The class was designed to be POD initialized, so it shouldn't require a
+// static constructor. It really only makes sense to declare a LazyInstance as
+// a global variable using the base::LinkerInitialized constructor.
+//
+// LazyInstance is similar to Singleton, except it does not have the singleton
+// property. You can have multiple LazyInstance's of the same type, and each
+// will manage a unique instance. It also preallocates the space for Type, as
+// to avoid allocating the Type instance on the heap. This may help with the
+// performance of creating the instance, and reducing heap fragmentation. This
+// requires that Type be a complete type so we can determine the size.
+//
+// Example usage:
+// static LazyInstance<MyClass> my_instance(base::LINKER_INITALIZED);
+// void SomeMethod() {
+// my_instance.Get().SomeMethod(); // MyClass::SomeMethod()
+//
+// MyClass* ptr = my_instance.Pointer();
+// ptr->DoDoDo(); // MyClass::DoDoDo
+// }
+
+#ifndef BASE_LAZY_INSTANCE_H_
+#define BASE_LAZY_INSTANCE_H_
+
+#include "base/atomicops.h"
+#include "base/basictypes.h"
+
+namespace base {
+
+template <typename Type>
+struct DefaultLazyInstanceTraits {
+ static void New(void* instance) {
+ // Use placement new to initialize our instance in our preallocated space.
+ // The parenthesis is very important here to force POD type initialization.
+ new (instance) Type();
+ }
+ static void Delete(void* instance) {
+ // Explicitly call the destructor.
+ reinterpret_cast<Type*>(instance)->~Type();
+ }
+};
+
+// We pull out some of the functionality into a non-templated base, so that we
+// can implement the more complicated pieces out of line in the .cc file.
+class LazyInstanceHelper {
+ protected:
+ enum {
+ STATE_EMPTY = 0,
+ STATE_CREATING = 1,
+ STATE_CREATED = 2
+ };
+
+ explicit LazyInstanceHelper(LinkerInitialized x) { /* state_ is 0 */ }
+ ~LazyInstanceHelper() { }
+
+ // Make sure that instance is created, creating or waiting for it to be
+ // created if neccessary. Constructs with |ctor| in the space provided by
+ // |instance| and registers dtor for destruction at program exit.
+ void EnsureInstance(void* instance, void (*ctor)(void*), void (*dtor)(void*));
+
+ base::subtle::Atomic32 state_;
+};
+
+template <typename Type, typename Traits = DefaultLazyInstanceTraits<Type> >
+class LazyInstance : public LazyInstanceHelper {
+ public:
+ explicit LazyInstance(LinkerInitialized x) : LazyInstanceHelper(x) { }
+ ~LazyInstance() { }
+
+ Type& Get() {
+ return *Pointer();
+ }
+
+ Type* Pointer() {
+ Type* instance = reinterpret_cast<Type*>(&buf_);
+
+ // We will hopefully have fast access when the instance is already created.
+ if (base::subtle::NoBarrier_Load(&state_) != STATE_CREATED)
+ EnsureInstance(instance, Traits::New, Traits::Delete);
+
+ return instance;
+ }
+
+ private:
+ int8 buf_[sizeof(Type)]; // Preallocate the space for the Type instance.
+
+ DISALLOW_COPY_AND_ASSIGN(LazyInstance);
+};
+
+} // namespace base
+
+#endif // BASE_LAZY_INSTANCE_H_