TYPE3
[iec.git] / src / type3_AndroidCloud / anbox-master / external / android-emugl / shared / emugl / common / condition_variable_win32.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/condition_variable.h"
16
17 #include "emugl/common/lazy_instance.h"
18 #include "emugl/common/mutex.h"
19 #include "emugl/common/pod_vector.h"
20
21 // Technical note: this is loosely based on the Chromium implementation
22 // of ConditionVariable. This version works on Windows XP and above and
23 // doesn't try to use Vista's CONDITION_VARIABLE types.
24
25 namespace emugl {
26
27 namespace {
28
29 // Helper class which implements a free list of event handles.
30 class WaitEventStorage {
31 public:
32     WaitEventStorage() : mFreeHandles(), mLock() {}
33
34     ~WaitEventStorage() {
35         for (size_t n = 0; n < mFreeHandles.size(); ++n) {
36             CloseHandle(mFreeHandles[n]);
37         }
38     }
39
40     HANDLE alloc() {
41         HANDLE handle;
42         mLock.lock();
43         size_t size = mFreeHandles.size();
44         if (size > 0) {
45             handle = mFreeHandles[size - 1U];
46             mFreeHandles.remove(size - 1U);
47         } else {
48             handle = CreateEvent(NULL, TRUE, FALSE, NULL);
49         }
50         mLock.unlock();
51         return handle;
52     }
53
54     void free(HANDLE h) {
55         mLock.lock();
56         ResetEvent(h);
57         mFreeHandles.push_back(h);
58         mLock.unlock();
59     }
60
61 private:
62     PodVector<HANDLE> mFreeHandles;
63     Mutex mLock;
64 };
65
66 LazyInstance<WaitEventStorage> sWaitEvents = LAZY_INSTANCE_INIT;
67
68 }  // namespace
69
70 ConditionVariable::ConditionVariable() : mWaiters(), mLock() {}
71
72 ConditionVariable::~ConditionVariable() {
73     mLock.lock();
74     for (size_t n = 0; n < mWaiters.size(); ++n) {
75         CloseHandle(mWaiters[n]);
76     }
77     mWaiters.resize(0U);
78     mLock.unlock();
79 }
80
81 void ConditionVariable::wait(Mutex* userLock) {
82     // Grab new waiter event handle.
83     mLock.lock();
84     HANDLE handle = sWaitEvents->alloc();
85     mWaiters.push_back(handle);
86     mLock.unlock();
87
88     // Unlock user lock then wait for event.
89     userLock->unlock();
90     WaitForSingleObject(handle, INFINITE);
91     // NOTE: The handle has been removed from mWaiters here,
92     // see signal() below. Close/recycle the event.
93     sWaitEvents->free(handle);
94     userLock->lock();
95 }
96
97 void ConditionVariable::signal() {
98     mLock.lock();
99     size_t size = mWaiters.size();
100     if (size > 0U) {
101         // NOTE: This wakes up the thread that went to sleep most
102         //       recently (LIFO) for performance reason. For better
103         //       fairness, using (FIFO) would be appropriate.
104         HANDLE handle = mWaiters[size - 1U];
105         mWaiters.remove(size - 1U);
106         SetEvent(handle);
107         // NOTE: The handle will be closed/recycled by the waiter.
108     } else {
109         // Nothing to signal.
110     }
111     mLock.unlock();
112 }
113
114 }  // namespace emugl