TYPE3
[iec.git] / src / type3_AndroidCloud / anbox-master / external / android-emugl / shared / emugl / common / lazy_instance.h
1 // Copyright (C) 2014 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 #ifndef EMUGL_COMMON_LAZY_INSTANCE_H
16 #define EMUGL_COMMON_LAZY_INSTANCE_H
17
18 #include <new>
19
20 #ifdef _WIN32
21 #  define WIN32_LEAN_AND_MEAN 1
22 #  include <windows.h>
23 #endif
24
25 namespace emugl {
26 namespace internal {
27
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.
31 //
32 // In a nutshell, you can replace a statement like:
33 //
34 //    static Foo gFoo;
35 //
36 // With:
37 //
38 //    static LazyInstance<Foo> gFoo = LAZY_INSTANCE_INIT;
39 //
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.
43 //
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.
46 //
47 // Note that access is slightly different, i.e.:
48 //
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().
52 //
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.:
57 //
58 //    class FoorWithDefaultParams : public Foo {
59 //    public:
60 //       FooWithDefaultParams() : Foo(<default-parameters>) {}
61 //    };
62 //
63 //    LazyInstance<FooWithDefaultParams> gFoo = LAZY_INSTANCE_INIT;
64 //
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.
69 //
70 // You can also use LazyInstance<> instances as static local variables,
71 // e.g.:
72 //
73 //     Foo*  getFooSingleton() {
74 //        static LazyInstance<Foo> sFoo = LAZY_INSTANCE_INIT;
75 //        return sFoo.ptr();
76 //     }
77 //
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.
81 //
82 // This class is heavily inspired by Chromium's implementation of the
83 // same-named class (see $CHROMIUM/src/base/lazy_instance.h).
84
85 // Atomic state variable type. Used to ensure to synchronize concurrent
86 // initialization and access without incurring the full cost of a mutex
87 // lock/unlock.
88 struct LazyInstanceState {
89     enum {
90         STATE_INIT = 0,
91         STATE_CONSTRUCTING = 1,
92         STATE_DONE = 2,
93     };
94
95     bool inInitState();
96     bool needConstruction();
97     void doneConstructing();
98
99 #ifdef _WIN32
100     typedef LONG volatile AtomicType;
101 #else
102     typedef int volatile AtomicType;
103 #endif
104
105     volatile AtomicType mState;
106 };
107
108 #define LAZY_INSTANCE_STATE_INIT  \
109     { ::emugl::internal::LazyInstanceState::STATE_INIT }
110
111 }  // namespace internal
112
113 // LazyInstance template definition, see comment above for usage
114 // instructions. It is crucial to make this a POD-struct compatible
115 // type [1].
116 //
117 // [1] http://en.wikipedia.org/wiki/Plain_Old_Data_Structures
118 //
119 template <class T>
120 struct LazyInstance {
121     bool hasInstance() const { return !mState.inInitState(); }
122
123     T& get() const { return *ptr(); }
124
125     T* ptr() const;
126
127     const T* operator->() const { return ptr(); }
128
129     T* operator->() { return ptr(); }
130
131     T& operator*() { return get(); }
132
133     // Really private, do not use.
134     union {
135         mutable internal::LazyInstanceState mState;
136         double mPadding;
137     };
138     mutable char mStorage[sizeof(T)];
139 };
140
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 } }
144
145 template <class T>
146 T* LazyInstance<T>::ptr() const {
147     if (mState.needConstruction()) {
148         new (mStorage) T();
149         mState.doneConstructing();
150     }
151     return reinterpret_cast<T*>(mStorage);
152 }
153
154 }  // namespace emugl
155
156 #endif  // EMUGL_COMMON_LAZY_INSTANCE_H