TYPE3
[iec.git] / src / type3_AndroidCloud / anbox-master / external / android-emugl / shared / emugl / common / lazy_instance.cpp
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 #include "emugl/common/lazy_instance.h"
16
17 #ifdef _WIN32
18 #  define WIN32_LEAN_AND_MEAN 1
19 #  include <windows.h>
20 #else
21 #  include <sched.h>
22 #endif
23
24 namespace emugl {
25 namespace internal {
26
27 typedef LazyInstanceState::AtomicType AtomicType;
28
29 #if defined(__GNUC__)
30 static inline void compilerBarrier() {
31     __asm__ __volatile__ ("" : : : "memory");
32 }
33 #else
34 #error "Your compiler is not supported"
35 #endif
36
37 #if defined(__i386__) || defined(__x86_64__) || defined(__arm__) || defined(__aarch64__)
38 #  define acquireBarrier() compilerBarrier()
39 #  define releaseBarrier() compilerBarrier()
40 #else
41 #  error "Your CPU is not supported"
42 #endif
43
44 static inline AtomicType loadAcquire(AtomicType volatile* ptr) {
45     AtomicType ret = *ptr;
46     acquireBarrier();
47     return ret;
48 }
49
50 static inline void storeRelease(AtomicType volatile* ptr, AtomicType value) {
51     releaseBarrier();
52     *ptr = value;
53 }
54
55 static int atomicCompareAndSwap(AtomicType volatile* ptr,
56                                 int expected,
57                                 int value) {
58 #ifdef _WIN32
59     return InterlockedCompareExchange(ptr, value, expected);
60 #elif defined(__GNUC__)
61     return __sync_val_compare_and_swap(ptr, expected, value);
62 #else
63 #error "Your compiler is not supported"
64 #endif
65 }
66
67 static void yieldThread() {
68 #ifdef _WIN32
69     ::Sleep(0);
70 #else
71     sched_yield();
72 #endif
73 }
74
75 bool LazyInstanceState::inInitState() {
76     return loadAcquire(&mState) == STATE_INIT;
77 }
78
79 bool LazyInstanceState::needConstruction() {
80     AtomicType state = loadAcquire(&mState);
81     if (mState == STATE_DONE)
82         return false;
83
84     state = atomicCompareAndSwap(&mState, STATE_INIT, STATE_CONSTRUCTING);
85     if (state == STATE_INIT)
86         return true;
87
88     do {
89         yieldThread();
90         state = loadAcquire(&mState);
91     } while (state != STATE_DONE);
92
93     return false;
94 }
95
96 void LazyInstanceState::doneConstructing() {
97     storeRelease(&mState, STATE_DONE);
98 }
99
100 }  // namespace internal
101 }  // namespace emugl