testThreadingConditionVariable.cpp (6300B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- 2 * vim: set ts=8 sts=2 et sw=2 tw=80: 3 */ 4 /* This Source Code Form is subject to the terms of the Mozilla Public 5 * License, v. 2.0. If a copy of the MPL was not distributed with this 6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 7 8 #include "jsapi-tests/tests.h" 9 #include "threading/ConditionVariable.h" 10 #include "threading/Thread.h" 11 #include "vm/MutexIDs.h" 12 13 struct TestState { 14 js::Mutex mutex MOZ_UNANNOTATED; 15 js::ConditionVariable condition; 16 bool flag; 17 js::Thread testThread; 18 19 explicit TestState(bool createThread = true) 20 : mutex(js::mutexid::TestMutex), flag(false) { 21 if (createThread) { 22 MOZ_RELEASE_ASSERT(testThread.init(setFlag, this)); 23 } 24 } 25 26 static void setFlag(TestState* state) { 27 js::UniqueLock<js::Mutex> lock(state->mutex); 28 state->flag = true; 29 state->condition.notify_one(); 30 } 31 32 void join() { testThread.join(); } 33 }; 34 35 BEGIN_TEST(testThreadingConditionVariable) { 36 auto state = mozilla::MakeUnique<TestState>(); 37 { 38 js::UniqueLock<js::Mutex> lock(state->mutex); 39 while (!state->flag) { 40 state->condition.wait(lock); 41 } 42 } 43 state->join(); 44 45 CHECK(state->flag); 46 47 return true; 48 } 49 END_TEST(testThreadingConditionVariable) 50 51 BEGIN_TEST(testThreadingConditionVariablePredicate) { 52 auto state = mozilla::MakeUnique<TestState>(); 53 { 54 js::UniqueLock<js::Mutex> lock(state->mutex); 55 state->condition.wait(lock, [&state]() { return state->flag; }); 56 } 57 state->join(); 58 59 CHECK(state->flag); 60 61 return true; 62 } 63 END_TEST(testThreadingConditionVariablePredicate) 64 65 BEGIN_TEST(testThreadingConditionVariableUntilOkay) { 66 auto state = mozilla::MakeUnique<TestState>(); 67 { 68 js::UniqueLock<js::Mutex> lock(state->mutex); 69 while (!state->flag) { 70 auto to = 71 mozilla::TimeStamp::Now() + mozilla::TimeDuration::FromSeconds(600); 72 js::CVStatus res = state->condition.wait_until(lock, to); 73 CHECK(res == js::CVStatus::NoTimeout); 74 } 75 } 76 state->join(); 77 78 CHECK(state->flag); 79 80 return true; 81 } 82 END_TEST(testThreadingConditionVariableUntilOkay) 83 84 BEGIN_TEST(testThreadingConditionVariableUntilTimeout) { 85 auto state = mozilla::MakeUnique<TestState>(false); 86 { 87 js::UniqueLock<js::Mutex> lock(state->mutex); 88 while (!state->flag) { 89 auto to = mozilla::TimeStamp::Now() + 90 mozilla::TimeDuration::FromMilliseconds(10); 91 js::CVStatus res = state->condition.wait_until(lock, to); 92 if (res == js::CVStatus::Timeout) { 93 break; 94 } 95 } 96 } 97 CHECK(!state->flag); 98 99 // Timeout in the past should return with timeout immediately. 100 { 101 js::UniqueLock<js::Mutex> lock(state->mutex); 102 auto to = 103 mozilla::TimeStamp::Now() - mozilla::TimeDuration::FromMilliseconds(10); 104 js::CVStatus res = state->condition.wait_until(lock, to); 105 CHECK(res == js::CVStatus::Timeout); 106 } 107 108 return true; 109 } 110 END_TEST(testThreadingConditionVariableUntilTimeout) 111 112 BEGIN_TEST(testThreadingConditionVariableUntilOkayPredicate) { 113 auto state = mozilla::MakeUnique<TestState>(); 114 { 115 js::UniqueLock<js::Mutex> lock(state->mutex); 116 auto to = 117 mozilla::TimeStamp::Now() + mozilla::TimeDuration::FromSeconds(600); 118 bool res = state->condition.wait_until(lock, to, 119 [&state]() { return state->flag; }); 120 CHECK(res); 121 } 122 state->join(); 123 124 CHECK(state->flag); 125 126 return true; 127 } 128 END_TEST(testThreadingConditionVariableUntilOkayPredicate) 129 130 BEGIN_TEST(testThreadingConditionVariableUntilTimeoutPredicate) { 131 auto state = mozilla::MakeUnique<TestState>(false); 132 { 133 js::UniqueLock<js::Mutex> lock(state->mutex); 134 auto to = 135 mozilla::TimeStamp::Now() + mozilla::TimeDuration::FromMilliseconds(10); 136 bool res = state->condition.wait_until(lock, to, 137 [&state]() { return state->flag; }); 138 CHECK(!res); 139 } 140 CHECK(!state->flag); 141 142 return true; 143 } 144 END_TEST(testThreadingConditionVariableUntilTimeoutPredicate) 145 146 BEGIN_TEST(testThreadingConditionVariableForOkay) { 147 auto state = mozilla::MakeUnique<TestState>(); 148 { 149 js::UniqueLock<js::Mutex> lock(state->mutex); 150 while (!state->flag) { 151 auto duration = mozilla::TimeDuration::FromSeconds(600); 152 js::CVStatus res = state->condition.wait_for(lock, duration); 153 CHECK(res == js::CVStatus::NoTimeout); 154 } 155 } 156 state->join(); 157 158 CHECK(state->flag); 159 160 return true; 161 } 162 END_TEST(testThreadingConditionVariableForOkay) 163 164 BEGIN_TEST(testThreadingConditionVariableForTimeout) { 165 auto state = mozilla::MakeUnique<TestState>(false); 166 { 167 js::UniqueLock<js::Mutex> lock(state->mutex); 168 while (!state->flag) { 169 auto duration = mozilla::TimeDuration::FromMilliseconds(10); 170 js::CVStatus res = state->condition.wait_for(lock, duration); 171 if (res == js::CVStatus::Timeout) { 172 break; 173 } 174 } 175 } 176 CHECK(!state->flag); 177 178 // Timeout in the past should return with timeout immediately. 179 { 180 js::UniqueLock<js::Mutex> lock(state->mutex); 181 auto duration = mozilla::TimeDuration::FromMilliseconds(-10); 182 js::CVStatus res = state->condition.wait_for(lock, duration); 183 CHECK(res == js::CVStatus::Timeout); 184 } 185 186 return true; 187 } 188 END_TEST(testThreadingConditionVariableForTimeout) 189 190 BEGIN_TEST(testThreadingConditionVariableForOkayPredicate) { 191 auto state = mozilla::MakeUnique<TestState>(); 192 { 193 js::UniqueLock<js::Mutex> lock(state->mutex); 194 auto duration = mozilla::TimeDuration::FromSeconds(600); 195 bool res = state->condition.wait_for(lock, duration, 196 [&state]() { return state->flag; }); 197 CHECK(res); 198 } 199 state->join(); 200 201 CHECK(state->flag); 202 203 return true; 204 } 205 END_TEST(testThreadingConditionVariableForOkayPredicate) 206 207 BEGIN_TEST(testThreadingConditionVariableForTimeoutPredicate) { 208 auto state = mozilla::MakeUnique<TestState>(false); 209 { 210 js::UniqueLock<js::Mutex> lock(state->mutex); 211 auto duration = mozilla::TimeDuration::FromMilliseconds(10); 212 bool res = state->condition.wait_for(lock, duration, 213 [&state]() { return state->flag; }); 214 CHECK(!res); 215 } 216 CHECK(!state->flag); 217 218 return true; 219 } 220 END_TEST(testThreadingConditionVariableForTimeoutPredicate)