bool Condition::wait(UniqueLock<honey::Mutex>& external, honey::MonoClock::TimePoint time) { honey::thread::priv::InterruptWait _(reinterpret_cast<honey::Condition&>(*this), external.mutex()); timespec time_; //platform bug, should allow numeral<decltype(time_.tv_sec)>().max() time_.tv_sec = Alge::min(Seconds(time.time()).count(), numeral<int>().max()); time_.tv_nsec = time.time() % Seconds(1); return !pthread_cond_timedwait(&_handle, &external.mutex().handle(), &time_); }
void DatabasesCloner::_cancelCloners_inlock(UniqueLock& lk) { std::vector<std::shared_ptr<DatabaseCloner>> clonersToCancel; for (auto&& cloner : _databaseCloners) { if (cloner && cloner->isActive()) { clonersToCancel.push_back(cloner); } } lk.unlock(); for (auto&& cloner : clonersToCancel) { cloner->cancel(); } lk.lock(); }
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()
void DatabasesCloner::_failed_inlock(UniqueLock& lk) { LOG(3) << "DatabasesCloner::_failed_inlock"; if (!_active) { return; } _active = false; // TODO: shutdown outstanding work, like any cloners active auto finish = _finishFn; lk.unlock(); LOG(3) << "calling _finishFn with status: " << _status; _finishFn(_status); }
void DatabaseCloner::_finishCallback_inlock(UniqueLock& lk, const Status& status) { if (lk.owns_lock()) { lk.unlock(); } _finishCallback(status); }