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 
98 // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! DEPRECATED !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
99 // Please don't use this macro. Use a function-local static of type
100 // android::base::NoDestructor<T> instead:
101 //
102 // Factory& Factory::GetInstance() {
103 //   static base::NoDestructor<Factory> instance;
104 //   return *instance;
105 // }
106 //
107 // From C++20 onwards this will no longer compile. See:
108 // See https://github.com/microsoft/STL/issues/661
109 // For details on issues and guarantees around atomic initialization.
110 // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
111 struct LazyInstanceState {
112     enum class State : char {
113         Init = 0,
114         Constructing = 1,
115         Done = 2,
116         Destroying = 3,
117     };
118 
119     bool inNoObjectState() const;
120     bool needConstruction();
121     void doneConstructing();
122 
123     bool needDestruction();
124     void doneDestroying();
125 
126     std::atomic<State> mState;
127 };
128 
129 static_assert(std::is_standard_layout<LazyInstanceState>::value,
130               "LazyInstanceState is not a standard layout type");
131 #ifndef _MSC_VER
132 static_assert(is_trivially_default_constructible<LazyInstanceState>::value,
133               "LazyInstanceState can't be trivially default constructed");
134 #endif
135 }  // namespace internal
136 
137 class Lock;
138 class StaticLock;
139 
140 // LazyInstance template definition, see comment above for usage
141 // instructions. It is crucial to make this a POD-struct compatible
142 // type [1].
143 //
144 // [1] http://en.wikipedia.org/wiki/Plain_Old_Data_Structures
145 //
146 template <class T>
147 struct LazyInstance {
148     static_assert(!std::is_same<T, Lock>::value &&
149                           !std::is_same<T, StaticLock>::value,
150                   "Don't use LazyInstance<Lock | StaticLock>, use StaticLock "
151                   "by value instead");
152 
hasInstanceLazyInstance153     bool hasInstance() const { return !mState.inNoObjectState(); }
154 
getLazyInstance155     const T& get() const { return *ptr(); }
getLazyInstance156     T& get() { return *ptr(); }
157 
158     const T* operator->() const { return ptr(); }
159     T* operator->() { return ptr(); }
160 
161     const T& operator*() const { return get(); }
162     T& operator*() { return get(); }
163 
ptrLazyInstance164     T* ptr() { return ptrInternal(); }
ptrLazyInstance165     const T* ptr() const { return ptrInternal(); }
166 
clearLazyInstance167     void clear() {
168         if (mState.needDestruction()) {
169             reinterpret_cast<T*>(&mStorage)->~T();
170             mState.doneDestroying();
171         }
172     }
173 
174 private:
175     T* ptrInternal() const;
176 
177     using StorageT =
178             typename std::aligned_storage<sizeof(T),
179                                           std::alignment_of<T>::value>::type;
180 
181     alignas(double) mutable internal::LazyInstanceState mState;
182     mutable StorageT mStorage;
183 };
184 
185 // Initialization value, must resolve to all-0 to ensure the object
186 // instance is actually placed in the .bss
187 #define LAZY_INSTANCE_INIT \
188     {}
189 
190 template <class T>
ptrInternal()191 T* LazyInstance<T>::ptrInternal() const {
192     // Make sure that LazyInstance<> instantiation remains static.
193     // NB: this can't go in a class scope as class is still incomplete there.
194     static_assert(std::is_standard_layout<LazyInstance>::value,
195                   "LazyInstance<T> is not a standard layout type");
196 #ifndef _MSC_VER
197     // These checks are not working in vs2019..
198     static_assert(
199             internal::is_trivially_default_constructible<LazyInstance>::value,
200             "LazyInstance<T> can't be trivially default constructed");
201 #endif
202     if (mState.needConstruction()) {
203         new (&mStorage) T();
204         mState.doneConstructing();
205     }
206     return reinterpret_cast<T*>(&mStorage);
207 }
208 
209 }  // namespace base
210 }  // namespace android
211