cv_status wait_until( LockType & lt, std::chrono::time_point< Clock, Duration > const& timeout_time_) { context * active_ctx = context::active(); cv_status status = cv_status::no_timeout; std::chrono::steady_clock::time_point timeout_time = detail::convert( timeout_time_); // atomically call lt.unlock() and block on *this // store this fiber in waiting-queue detail::spinlock_lock lk{ wait_queue_splk_ }; BOOST_ASSERT( ! active_ctx->wait_is_linked() ); active_ctx->wait_link( wait_queue_); // unlock external lt lt.unlock(); // suspend this fiber if ( ! active_ctx->wait_until( timeout_time, lk) ) { status = cv_status::timeout; // relock local lk lk.lock(); // remove from waiting-queue wait_queue_.remove( * active_ctx); // unlock local lk lk.unlock(); } // relock external again before returning try { lt.lock(); } catch (...) { std::terminate(); } // post-conditions BOOST_ASSERT( ! active_ctx->wait_is_linked() ); return status; }
void wait( LockType & lt) { 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 ctx->suspend( lk); // 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() ); }
void wait( LockType & lt) { detail::notify::ptr_t n( detail::scheduler::instance().active() ); try { if ( n) { // store this fiber in order to be notified later unique_lock< detail::spinlock > lk( waiting_mtx_); waiting_.push_back( n); lt.unlock(); // suspend fiber detail::scheduler::instance().wait( lk); // check if fiber was interrupted this_fiber::interruption_point(); } else { // notifier for main-fiber n = detail::scheduler::instance().notifier(); // store this fiber in order to be notified later unique_lock< detail::spinlock > lk( waiting_mtx_); waiting_.push_back( n); lk.unlock(); lt.unlock(); while ( ! n->is_ready() ) { fprintf(stdout, "condition: main-fiber not woken-up\n"); // run scheduler detail::scheduler::instance().run(); } fprintf(stdout, "condition: main-fiber woken-up\n"); } } catch (...) { // remove fiber from waiting_ unique_lock< detail::spinlock > lk( waiting_mtx_); waiting_.erase( std::find( waiting_.begin(), waiting_.end(), n) ); throw; } // lock external again before returning lt.lock(); }
void wait( LockType & lt) { detail::notify::ptr_t n( detail::scheduler::instance()->active() ); try { if ( n) { // store this fiber in order to be notified later waiting_.push_back( n); lt.unlock(); // suspend fiber detail::scheduler::instance()->wait(); // check if fiber was interrupted this_fiber::interruption_point(); } else { // notifier for main-fiber detail::main_notifier mn; n = detail::main_notifier::make_pointer( mn); // store this fiber in order to be notified later waiting_.push_back( n); lt.unlock(); while ( ! n->is_ready() ) { // run scheduler detail::scheduler::instance()->run(); } } } catch (...) { // remove fiber from waiting-list waiting_.erase( std::find( waiting_.begin(), waiting_.end(), n) ); throw; } // lock external again before returning lt.lock(); }
void wait( LockType & lt) { { mutex::scoped_lock lk( enter_mtx_); BOOST_ASSERT( lk); ++waiters_; lt.unlock(); } bool unlock_enter_mtx = false; for (;;) { while ( SLEEPING == cmd_) strategy_->wait_for_object( id_); mutex::scoped_lock lk( check_mtx_); BOOST_ASSERT( lk); if ( SLEEPING == cmd_) continue; else if ( NOTIFY_ONE == cmd_) { cmd_ = SLEEPING; unlock_enter_mtx = true; --waiters_; break; } else { unlock_enter_mtx = 0 == --waiters_; if ( unlock_enter_mtx) cmd_ = SLEEPING; break; } } if ( unlock_enter_mtx) enter_mtx_.unlock(); lt.lock(); }
static bool isFullyReset(LockType& lock) { return lock.isFullyReset(); }
explicit upgrade_to_unique_lock(LockType& other) { lockable_ = other.release(); if (lockable_) lockable_->unlock_upgrade_and_lock(); }
void unlock() const { state.store(Unlocked, std::memory_order_release); }
bool try_lock() const { return state.exchange(Locked, std::memory_order_acquire) != Locked; }
upgrade_to_unique_lock(LockType& other) { m_lockable = other.release(); if (m_lockable) m_lockable->lock_upgrade(); }
void wait( LockType & lt) { detail::fiber_base * n( fm_active() ); try { if ( n) { // lock spinlock unique_lock< detail::spinlock > lk( splk_); BOOST_ASSERT( waiting_.end() == std::find( waiting_.begin(), waiting_.end(), n) ); // 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 fm_wait( lk); // this fiber was notified and resumed // 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_); BOOST_ASSERT( waiting_.end() == std::find( waiting_.begin(), waiting_.end(), n) ); // store this main-notifier in waiting-queue // 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() ) // 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; } }
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; }
cv_status wait_until( LockType & lt, clock_type::time_point const& timeout_time) { cv_status status = cv_status::no_timeout; detail::notify::ptr_t n( detail::scheduler::instance()->active() ); try { if ( n) { // store this fiber in order to be notified later waiting_.push_back( n); lt.unlock(); // suspend fiber if ( ! detail::scheduler::instance()->wait_until( timeout_time) ) { // remove fiber from waiting-list waiting_.erase( std::find( waiting_.begin(), waiting_.end(), n) ); status = cv_status::timeout; } // check if fiber was interrupted this_fiber::interruption_point(); } else { // notifier for main-fiber detail::main_notifier mn; n = detail::main_notifier::make_pointer( mn); // store this fiber in order to be notified later waiting_.push_back( n); lt.unlock(); while ( ! n->is_ready() ) { if ( ! ( clock_type::now() < timeout_time) ) { // remove fiber from waiting-list waiting_.erase( std::find( waiting_.begin(), waiting_.end(), n) ); status = cv_status::timeout; break; } // run scheduler detail::scheduler::instance()->run(); } } } catch (...) { // remove fiber from waiting-list waiting_.erase( std::find( waiting_.begin(), waiting_.end(), n) ); throw; } // lock external again before returning lt.lock(); return status; }