value_type value_pop() { for (;;) { slot * s{ nullptr }; std::size_t idx{ 0 }; channel_op_status status{ try_value_pop_( s, idx) }; if ( channel_op_status::success == status) { value_type value{ std::move( * reinterpret_cast< value_type * >( std::addressof( s->storage) ) ) }; s->cycle.store( idx + capacity_, std::memory_order_release); not_full_cnd_.notify_one(); return std::move( value); } else if ( channel_op_status::empty == status) { std::unique_lock< std::mutex > lk{ mtx_ }; ++waiting_consumer_; if ( is_closed() ) { throw std::runtime_error{ "boost fiber: channel is closed" }; } if ( ! is_empty_() ) { continue; } not_empty_cnd_.wait( lk, [this](){ return is_closed() || ! is_empty_(); }); --waiting_consumer_; } else { BOOST_ASSERT( channel_op_status::closed == status); throw std::runtime_error{ "boost fiber: channel is closed" }; } } }
channel_op_status pop( value_type & va) { std::unique_lock< mutex > lk( mtx_); not_empty_cond_.wait( lk, [this](){ return is_closed_() || ! is_empty_(); }); if ( is_closed_() && is_empty_() ) { return channel_op_status::closed; } va = value_pop_( lk); return channel_op_status::success; }
value_type value_pop() { std::unique_lock< mutex > lk( mtx_); not_empty_cond_.wait( lk, [this](){ return is_closed_() || ! is_empty_(); }); if ( is_closed_() && is_empty_() ) { throw fiber_error( std::make_error_code( std::errc::operation_not_permitted), "boost fiber: queue is closed"); } return value_pop_( lk); }
channel_op_status pop_wait_until( value_type & va, std::chrono::time_point< Clock, Duration > const& timeout_time) { std::unique_lock< mutex > lk( mtx_); if ( ! not_empty_cond_.wait_until( lk, timeout_time, [this](){ return is_closed_() || ! is_empty_(); })) { return channel_op_status::timeout; } if ( is_closed_() && is_empty_() ) { return channel_op_status::closed; } va = value_pop_( lk); return channel_op_status::success; }
channel_op_status try_pop( value_type & va) { std::unique_lock< mutex > lk( mtx_); if ( is_closed_() && is_empty_() ) { // let other fibers run lk.unlock(); this_fiber::yield(); return channel_op_status::closed; } if ( is_empty_() ) { // let other fibers run lk.unlock(); this_fiber::yield(); return channel_op_status::empty; } va = value_pop_( lk); return channel_op_status::success; }
context * pop() { spinlock_lock lk{ splk_ }; context * c = nullptr; if ( ! is_empty_() ) { c = slots_[cidx_]; cidx_ = (cidx_ + 1) % capacity_; } return c; }
context * steal() { spinlock_lock lk{ splk_ }; context * c = nullptr; if ( ! is_empty_() ) { c = slots_[cidx_]; if ( c->is_context( type::pinned_context) ) { return nullptr; } cidx_ = (cidx_ + 1) % capacity_; } return c; }
value_type value_pop_( std::unique_lock< mutex > & lk) { BOOST_ASSERT( ! is_empty_() ); auto old_head = pop_head_(); return std::move( old_head->va); }
bool empty() const noexcept { spinlock_lock lk{ splk_ }; return is_empty_(); }