1 // Copyright (C) 2014 The Android Open Source Project
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
7 // http://www.apache.org/licenses/LICENSE-2.0
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.
15 #include "emugl/common/condition_variable.h"
17 #include "emugl/common/lazy_instance.h"
18 #include "emugl/common/mutex.h"
19 #include "emugl/common/pod_vector.h"
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.
29 // Helper class which implements a free list of event handles.
30 class WaitEventStorage {
32 WaitEventStorage() : mFreeHandles(), mLock() {}
35 for (size_t n = 0; n < mFreeHandles.size(); ++n) {
36 CloseHandle(mFreeHandles[n]);
43 size_t size = mFreeHandles.size();
45 handle = mFreeHandles[size - 1U];
46 mFreeHandles.remove(size - 1U);
48 handle = CreateEvent(NULL, TRUE, FALSE, NULL);
57 mFreeHandles.push_back(h);
62 PodVector<HANDLE> mFreeHandles;
66 LazyInstance<WaitEventStorage> sWaitEvents = LAZY_INSTANCE_INIT;
70 ConditionVariable::ConditionVariable() : mWaiters(), mLock() {}
72 ConditionVariable::~ConditionVariable() {
74 for (size_t n = 0; n < mWaiters.size(); ++n) {
75 CloseHandle(mWaiters[n]);
81 void ConditionVariable::wait(Mutex* userLock) {
82 // Grab new waiter event handle.
84 HANDLE handle = sWaitEvents->alloc();
85 mWaiters.push_back(handle);
88 // Unlock user lock then wait for event.
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);
97 void ConditionVariable::signal() {
99 size_t size = mWaiters.size();
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);
107 // NOTE: The handle will be closed/recycled by the waiter.
109 // Nothing to signal.