1 // Copyright (C) 2014-2015 The Android Open Source Project
2 //
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
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
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.
14 
15 #pragma once
16 
17 #include <atomic>
18 #include <new>
19 #include <type_traits>
20 
21 namespace android {
22 namespace base {
23 namespace internal {
24 
25 // Older GCC stdlib uses deprecated naming scheme has_xxx instead of is_xxx
26 #if (defined(__GNUC__) && !defined(__clang__) && __GNUC__ <= 4) || \
27         defined(__OLD_STD_VERSION__)
28 template <class T>
29 using is_trivially_default_constructible =
30         std::has_trivial_default_constructor<T>;
31 #else
32 template <class T>
33 using is_trivially_default_constructible =
34         std::is_trivially_default_constructible<T>;
35 #endif
36 
37 // A LazyInstance is a helper template that can be used to perform
38 // thread-safe lazy initialization of static C++ objects without forcing
39 // the generation of C++ static constructors in the final executable.
40 //
41 // In a nutshell, you can replace a statement like:
42 //
43 //    static Foo gFoo;
44 //
45 // With:
46 //
47 //    static LazyInstance<Foo> gFoo = LAZY_INSTANCE_INIT;
48 //
49 // In the first case, a hidden static C++ constructor is embedded in the
50 // final executable, and executed at *load* *time* to call the Foo::Foo
51 // constructor on the gFoo object.
52 //
53 // On the second case, gFoo will only be initialized lazily, i.e. the first
54 // time any code actually tries to access the variable.
55 //
56 // Note that access is slightly different, i.e.:
57 //
58 //    gFoo.get() returns a reference to the lazy-initialized object.
59 //    gFoo.ptr() returns a pointer to it.
60 //    gFoo->Something() is equivalent to doing gFoo.ptr()->Something().
61 //
62 // 'gFoo' is stored in the .bss section and this doesn't use heap allocation.
63 // This class can only be used to perform lazy initialization through the
64 // class' default constructor. For more specialized cases, you will have
65 // to create a derived class, e.g.:
66 //
67 //    class FoorWithDefaultParams : public Foo {
68 //    public:
69 //       FooWithDefaultParams() : Foo(<default-parameters>) {}
70 //    };
71 //
72 //    LazyInstance<FooWithDefaultParams> gFoo = LAZY_INSTANCE_INIT;
73 //
74 // The implementation of LazyInstance relies on atomic operations and
75 // POD-struct class definitions, i.e. one that doesn't have any constructor,
76 // destructor, virtual members, or private ones, and that can be
77 // zero-initialized at link time.
78 //
79 // You can also use LazyInstance<> instances as static local variables,
80 // e.g.:
81 //
82 //     Foo*  getFooSingleton() {
83 //        static LazyInstance<Foo> sFoo = LAZY_INSTANCE_INIT;
84 //        return sFoo.ptr();
85 //     }
86 //
87 // This is useful on Windows which doesn't support thread-safe lazy
88 // initialization of static C++ local variables, or on other platforms
89 // when the code is compiled with -fno-threadsafe-statics.
90 //
91 // This class is heavily inspired by Chromium's implementation of the
92 // same-named class (see $CHROMIUM/src/base/lazy_instance.h).
93 
94 // Atomic state variable type. Used to ensure to synchronize concurrent
95 // initialization and access without incurring the full cost of a mutex
96 // lock/unlock.
97 struct LazyInstanceState {
98     enum class State : char {
99         Init = 0,
100         Constructing = 1,
101         Done = 2,
102         Destroying = 3,
103     };
104 
105     bool inNoObjectState() const;
106     bool needConstruction();
107     void doneConstructing();
108 
109     bool needDestruction();
110     void doneDestroying();
111 
112     std::atomic<State> mState;
113 };
114 
115 static_assert(std::is_standard_layout<LazyInstanceState>::value,
116               "LazyInstanceState is not a standard layout type");
117 #ifndef _MSC_VER
118 static_assert(is_trivially_default_constructible<LazyInstanceState>::value,
119               "LazyInstanceState can't be trivially default constructed");
120 #endif
121 }  // namespace internal
122 
123 class Lock;
124 class StaticLock;
125 
126 // LazyInstance template definition, see comment above for usage
127 // instructions. It is crucial to make this a POD-struct compatible
128 // type [1].
129 //
130 // [1] http://en.wikipedia.org/wiki/Plain_Old_Data_Structures
131 //
132 template <class T>
133 struct LazyInstance {
134     static_assert(!std::is_same<T, Lock>::value &&
135                           !std::is_same<T, StaticLock>::value,
136                   "Don't use LazyInstance<Lock | StaticLock>, use StaticLock "
137                   "by value instead");
138 
hasInstanceLazyInstance139     bool hasInstance() const { return !mState.inNoObjectState(); }
140 
getLazyInstance141     const T& get() const { return *ptr(); }
getLazyInstance142     T& get() { return *ptr(); }
143 
144     const T* operator->() const { return ptr(); }
145     T* operator->() { return ptr(); }
146 
147     const T& operator*() const { return get(); }
148     T& operator*() { return get(); }
149 
ptrLazyInstance150     T* ptr() { return ptrInternal(); }
ptrLazyInstance151     const T* ptr() const { return ptrInternal(); }
152 
clearLazyInstance153     void clear() {
154         if (mState.needDestruction()) {
155             reinterpret_cast<T*>(&mStorage)->~T();
156             mState.doneDestroying();
157         }
158     }
159 
160 private:
161     T* ptrInternal() const;
162 
163     using StorageT =
164             typename std::aligned_storage<sizeof(T),
165                                           std::alignment_of<T>::value>::type;
166 
167     alignas(double) mutable internal::LazyInstanceState mState;
168     mutable StorageT mStorage;
169 };
170 
171 // Initialization value, must resolve to all-0 to ensure the object
172 // instance is actually placed in the .bss
173 #define LAZY_INSTANCE_INIT \
174     {}
175 
176 template <class T>
ptrInternal()177 T* LazyInstance<T>::ptrInternal() const {
178     // Make sure that LazyInstance<> instantiation remains static.
179     // NB: this can't go in a class scope as class is still incomplete there.
180     static_assert(std::is_standard_layout<LazyInstance>::value,
181                   "LazyInstance<T> is not a standard layout type");
182 #ifndef _MSC_VER
183     // These checks are not working in vs2019..
184     static_assert(
185             internal::is_trivially_default_constructible<LazyInstance>::value,
186             "LazyInstance<T> can't be trivially default constructed");
187 #endif
188     if (mState.needConstruction()) {
189         new (&mStorage) T();
190         mState.doneConstructing();
191     }
192     return reinterpret_cast<T*>(&mStorage);
193 }
194 
195 }  // namespace base
196 }  // namespace android
197