bool Condition::wait(UniqueLock<honey::Mutex>& external, honey::MonoClock::TimePoint time) { auto _ = ScopeGuard(lock::lockGuard(external)); _waitLock->lock(); ++_waitCount; _waitLock->unlock(); //Wait for both the semaphore and the high resolution timeout HANDLE handles[2] = { _sema }; int handleCount = 1; if (time != honey::MonoClock::TimePoint::max()) { //Convert to windows 100 nanosecond period, negative time means relative LARGE_INTEGER sleepTime; sleepTime.QuadPart = (-Alge::max(time - honey::MonoClock::now(), honey::MonoClock::Duration::zero()) / 100).count(); verify(SetWaitableTimer(_timer, &sleepTime, 0, NULL, NULL, 0)); handles[handleCount++] = _timer; } //Unfair but safe race condition: external unlock and wait should be atomic external.unlock(); DWORD res = WaitForMultipleObjects(handleCount, handles, FALSE, INFINITE); _waitLock->lock(); --_waitCount; bool lastWait = _broadcast && _waitCount == 0; _waitLock->unlock(); //Unfair but safe race condition: wait done signal and external relock should be atomic if (lastWait) SetEvent(_waitDone); return res == WAIT_OBJECT_0; } //external.lock()
ScopeGuard newScope(bool insideLoop) { return ScopeGuard(*this, insideLoop); }