1 // Copyright (C) 2014 The Android Open Source Project
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
7 // http://www.apache.org/licenses/LICENSE-2.0
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
15 #ifndef EMUGL_COMMON_LAZY_INSTANCE_H
16 #define EMUGL_COMMON_LAZY_INSTANCE_H
21 # define WIN32_LEAN_AND_MEAN 1
28 // A LazyInstance is a helper template that can be used to perform
29 // thread-safe lazy initialization of static C++ objects without forcing
30 // the generation of C++ static constructors in the final executable.
32 // In a nutshell, you can replace a statement like:
38 // static LazyInstance<Foo> gFoo = LAZY_INSTANCE_INIT;
40 // In the first case, a hidden static C++ constructor is embedded in the
41 // final executable, and executed at *load* *time* to call the Foo::Foo
42 // constructor on the gFoo object.
44 // On the second case, gFoo will only be initialized lazily, i.e. the first
45 // time any code actually tries to access the variable.
47 // Note that access is slightly different, i.e.:
49 // gFoo.get() returns a reference to the lazy-initialized object.
50 // gFoo.ptr() returns a pointer to it.
51 // gFoo->Something() is equivalent to doing gFoo.ptr()->Something().
53 // 'gFoo' is stored in the .bss section and this doesn't use heap allocation.
54 // This class can only be used to perform lazy initialization through the
55 // class' default constructor. For more specialized cases, you will have
56 // to create a derived class, e.g.:
58 // class FoorWithDefaultParams : public Foo {
60 // FooWithDefaultParams() : Foo(<default-parameters>) {}
63 // LazyInstance<FooWithDefaultParams> gFoo = LAZY_INSTANCE_INIT;
65 // The implementation of LazyInstance relies on atomic operations and
66 // POD-struct class definitions, i.e. one that doesn't have any constructor,
67 // destructor, virtual members, or private ones, and that can be
68 // zero-initialized at link time.
70 // You can also use LazyInstance<> instances as static local variables,
73 // Foo* getFooSingleton() {
74 // static LazyInstance<Foo> sFoo = LAZY_INSTANCE_INIT;
78 // This is useful on Windows which doesn't support thread-safe lazy
79 // initialization of static C++ local variables, or when the code is
80 // compiled with -fno-threadsafe-statics.
82 // This class is heavily inspired by Chromium's implementation of the
83 // same-named class (see $CHROMIUM/src/base/lazy_instance.h).
85 // Atomic state variable type. Used to ensure to synchronize concurrent
86 // initialization and access without incurring the full cost of a mutex
88 struct LazyInstanceState {
91 STATE_CONSTRUCTING = 1,
96 bool needConstruction();
97 void doneConstructing();
100 typedef LONG volatile AtomicType;
102 typedef int volatile AtomicType;
105 volatile AtomicType mState;
108 #define LAZY_INSTANCE_STATE_INIT \
109 { ::emugl::internal::LazyInstanceState::STATE_INIT }
111 } // namespace internal
113 // LazyInstance template definition, see comment above for usage
114 // instructions. It is crucial to make this a POD-struct compatible
117 // [1] http://en.wikipedia.org/wiki/Plain_Old_Data_Structures
120 struct LazyInstance {
121 bool hasInstance() const { return !mState.inInitState(); }
123 T& get() const { return *ptr(); }
127 const T* operator->() const { return ptr(); }
129 T* operator->() { return ptr(); }
131 T& operator*() { return get(); }
133 // Really private, do not use.
135 mutable internal::LazyInstanceState mState;
138 mutable char mStorage[sizeof(T)];
141 // Initialization value, must resolve to all-0 to ensure the object
142 // instance is actually placed in the .bss
143 #define LAZY_INSTANCE_INIT { { LAZY_INSTANCE_STATE_INIT }, { 0 } }
146 T* LazyInstance<T>::ptr() const {
147 if (mState.needConstruction()) {
149 mState.doneConstructing();
151 return reinterpret_cast<T*>(mStorage);
156 #endif // EMUGL_COMMON_LAZY_INSTANCE_H