cv_status wait_until( LockType & lt, std::chrono::time_point< Clock, Duration > const& timeout_time_) { cv_status status = cv_status::no_timeout; std::chrono::steady_clock::time_point timeout_time( detail::convert( timeout_time_) ); context * ctx = context::active(); // atomically call lt.unlock() and block on *this // store this fiber in waiting-queue detail::spinlock_lock lk( wait_queue_splk_); BOOST_ASSERT( ! ctx->wait_is_linked() ); ctx->wait_link( wait_queue_); // unlock external lt lt.unlock(); // suspend this fiber if ( ! ctx->wait_until( timeout_time, lk) ) { status = cv_status::timeout; } // relock local lk lk.lock(); // remove from waiting-queue ctx->wait_unlink(); // unlock local lk lk.unlock(); // relock external again before returning try { lt.lock(); } catch (...) { std::terminate(); } // post-conditions BOOST_ASSERT( ! ctx->wait_is_linked() ); return status; }
bool try_lock_until( std::chrono::time_point< Clock, Duration > const& timeout_time_) { std::chrono::steady_clock::time_point timeout_time( detail::convert( timeout_time_) ); return try_lock_until_( timeout_time); }
cv_status wait_until( LockType & lt, chrono::time_point< Clock, Duration > const& timeout_time_) { cv_status status = cv_status::no_timeout; chrono::high_resolution_clock::time_point timeout_time( detail::convert_tp( timeout_time_) ); detail::fiber_base * n( fm_active() ); try { if ( n) { // lock spinlock unique_lock< detail::spinlock > lk( splk_); // store this fiber in waiting-queue // in order notify (resume) this fiber later waiting_.push_back( n); // unlock external lt.unlock(); // suspend this fiber // locked spinlock will be released if this fiber // was stored inside schedulers's waiting-queue if ( ! fm_wait_until( timeout_time, lk) ) { // this fiber was not notified before timeout // lock spinlock again unique_lock< detail::spinlock > lk( splk_); std::deque< detail::fiber_base * >::iterator wit = std::find( waiting_.begin(), waiting_.end(), n); if (wit != waiting_.end()) { // remove fiber from waiting-list waiting_.erase( wit ); } status = cv_status::timeout; } // check if fiber was interrupted this_fiber::interruption_point(); // lock external again before returning lt.lock(); } else { // notification for main-fiber detail::main_fiber mf; n = & mf; // lock spinlock unique_lock< detail::spinlock > lk( splk_); // store this fiber in order to be notified later waiting_.push_back( n); // unlock external lt.unlock(); // release spinlock lk.unlock(); // loop until main-notifier gets notified while ( ! n->is_ready() ) { // check timepoint if ( ! ( chrono::high_resolution_clock::now() < timeout_time) ) { // timeout happend before notified // lock spinlock unique_lock< detail::spinlock > lk( splk_); std::deque< detail::fiber_base * >::iterator wit = std::find( waiting_.begin(), waiting_.end(), n); if (wit != waiting_.end()) { // remove fiber from waiting-list waiting_.erase(wit); } status = cv_status::timeout; break; } // run scheduler fm_run(); } // lock external again before returning lt.lock(); } } catch (...) { unique_lock< detail::spinlock > lk( splk_); std::deque< detail::fiber_base * >::iterator wit = std::find( waiting_.begin(), waiting_.end(), n); if (wit != waiting_.end()) { // remove fiber from waiting-list waiting_.erase( wit ); } throw; } return status; }