mirror of
https://github.com/boostorg/fiber.git
synced 2026-02-15 00:52:34 +00:00
implement condition_variable in terms of condition_variable_any
This commit is contained in:
@@ -23,6 +23,7 @@
|
||||
#include <boost/fiber/detail/spinlock.hpp>
|
||||
#include <boost/fiber/exceptions.hpp>
|
||||
#include <boost/fiber/interruption.hpp>
|
||||
#include <boost/fiber/mutex.hpp>
|
||||
#include <boost/fiber/operations.hpp>
|
||||
|
||||
#ifdef BOOST_HAS_ABI_HEADERS
|
||||
@@ -34,7 +35,7 @@ namespace fibers {
|
||||
|
||||
using cv_status = std::cv_status;
|
||||
|
||||
class BOOST_FIBERS_DECL condition_variable {
|
||||
class BOOST_FIBERS_DECL condition_variable_any {
|
||||
private:
|
||||
typedef context::wait_queue_t wait_queue_t;
|
||||
|
||||
@@ -42,33 +43,24 @@ private:
|
||||
detail::spinlock wait_queue_splk_{};
|
||||
|
||||
public:
|
||||
condition_variable() = default;
|
||||
condition_variable_any() = default;
|
||||
|
||||
~condition_variable() {
|
||||
~condition_variable_any() {
|
||||
BOOST_ASSERT( wait_queue_.empty() );
|
||||
}
|
||||
|
||||
condition_variable( condition_variable const&) = delete;
|
||||
condition_variable & operator=( condition_variable const&) = delete;
|
||||
condition_variable_any( condition_variable_any const&) = delete;
|
||||
condition_variable_any & operator=( condition_variable_any const&) = delete;
|
||||
|
||||
void notify_one() noexcept;
|
||||
|
||||
void notify_all() noexcept;
|
||||
|
||||
template< typename LockType, typename Pred >
|
||||
void wait( LockType & lt, Pred pred) {
|
||||
while ( ! pred() ) {
|
||||
wait( lt);
|
||||
}
|
||||
}
|
||||
|
||||
template< typename LockType >
|
||||
void wait( LockType & lt) {
|
||||
// check if context was interrupted
|
||||
this_fiber::interruption_point();
|
||||
context * ctx = context::active();
|
||||
// pre-conditions
|
||||
BOOST_ASSERT( lt.owns_lock() && ctx == lt.mutex()->owner_);
|
||||
// atomically call lt.unlock() and block on *this
|
||||
// store this fiber in waiting-queue
|
||||
detail::spinlock_lock lk( wait_queue_splk_);
|
||||
@@ -91,12 +83,18 @@ public:
|
||||
std::terminate();
|
||||
}
|
||||
// post-conditions
|
||||
BOOST_ASSERT( lt.owns_lock() && ctx == lt.mutex()->owner_);
|
||||
BOOST_ASSERT( ! ctx->wait_is_linked() );
|
||||
// check if context was interrupted
|
||||
this_fiber::interruption_point();
|
||||
}
|
||||
|
||||
template< typename LockType, typename Pred >
|
||||
void wait( LockType & lt, Pred pred) {
|
||||
while ( ! pred() ) {
|
||||
wait( lt);
|
||||
}
|
||||
}
|
||||
|
||||
template< typename LockType, typename Clock, typename Duration >
|
||||
cv_status wait_until( LockType & lt, std::chrono::time_point< Clock, Duration > const& timeout_time_) {
|
||||
// check if context was interrupted
|
||||
@@ -105,8 +103,6 @@ public:
|
||||
std::chrono::steady_clock::time_point timeout_time(
|
||||
detail::convert( timeout_time_) );
|
||||
context * ctx = context::active();
|
||||
// pre-conditions
|
||||
BOOST_ASSERT( lt.owns_lock() && ctx == lt.mutex()->owner_);
|
||||
// atomically call lt.unlock() and block on *this
|
||||
// store this fiber in waiting-queue
|
||||
detail::spinlock_lock lk( wait_queue_splk_);
|
||||
@@ -131,7 +127,6 @@ public:
|
||||
std::terminate();
|
||||
}
|
||||
// post-conditions
|
||||
BOOST_ASSERT( lt.owns_lock() && ctx == lt.mutex()->owner_);
|
||||
BOOST_ASSERT( ! ctx->wait_is_linked() );
|
||||
// check if context was interrupted
|
||||
this_fiber::interruption_point();
|
||||
@@ -163,7 +158,97 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
using condition_variable_any = condition_variable;
|
||||
class BOOST_FIBERS_DECL condition_variable {
|
||||
private:
|
||||
condition_variable_any cnd_;
|
||||
|
||||
public:
|
||||
condition_variable() = default;
|
||||
|
||||
condition_variable( condition_variable const&) = delete;
|
||||
condition_variable & operator=( condition_variable const&) = delete;
|
||||
|
||||
void notify_one() noexcept {
|
||||
cnd_.notify_one();
|
||||
}
|
||||
|
||||
void notify_all() noexcept {
|
||||
cnd_.notify_all();
|
||||
}
|
||||
|
||||
void wait( std::unique_lock< mutex > & lt) {
|
||||
// pre-condition
|
||||
BOOST_ASSERT( lt.owns_lock() );
|
||||
BOOST_ASSERT( context::active() == lt.mutex()->owner_);
|
||||
cnd_.wait( lt);
|
||||
// post-condition
|
||||
BOOST_ASSERT( lt.owns_lock() );
|
||||
BOOST_ASSERT( context::active() == lt.mutex()->owner_);
|
||||
}
|
||||
|
||||
template< typename Pred >
|
||||
void wait( std::unique_lock< mutex > & lt, Pred pred) {
|
||||
// pre-condition
|
||||
BOOST_ASSERT( lt.owns_lock() );
|
||||
BOOST_ASSERT( context::active() == lt.mutex()->owner_);
|
||||
cnd_.wait( lt, pred);
|
||||
// post-condition
|
||||
BOOST_ASSERT( lt.owns_lock() );
|
||||
BOOST_ASSERT( context::active() == lt.mutex()->owner_);
|
||||
}
|
||||
|
||||
template< typename Clock, typename Duration >
|
||||
cv_status wait_until( std::unique_lock< mutex > & lt,
|
||||
std::chrono::time_point< Clock, Duration > const& timeout_time) {
|
||||
// pre-condition
|
||||
BOOST_ASSERT( lt.owns_lock() );
|
||||
BOOST_ASSERT( context::active() == lt.mutex()->owner_);
|
||||
cv_status result = cnd_.wait_until( lt, timeout_time);
|
||||
// post-condition
|
||||
BOOST_ASSERT( lt.owns_lock() );
|
||||
BOOST_ASSERT( context::active() == lt.mutex()->owner_);
|
||||
return result;
|
||||
}
|
||||
|
||||
template< typename Clock, typename Duration, typename Pred >
|
||||
bool wait_until( std::unique_lock< mutex > & lt,
|
||||
std::chrono::time_point< Clock, Duration > const& timeout_time, Pred pred) {
|
||||
// pre-condition
|
||||
BOOST_ASSERT( lt.owns_lock() );
|
||||
BOOST_ASSERT( context::active() == lt.mutex()->owner_);
|
||||
bool result = cnd_.wait_until( lt, timeout_time, pred);
|
||||
// post-condition
|
||||
BOOST_ASSERT( lt.owns_lock() );
|
||||
BOOST_ASSERT( context::active() == lt.mutex()->owner_);
|
||||
return result;
|
||||
}
|
||||
|
||||
template< typename Rep, typename Period >
|
||||
cv_status wait_for( std::unique_lock< mutex > & lt,
|
||||
std::chrono::duration< Rep, Period > const& timeout_duration) {
|
||||
// pre-condition
|
||||
BOOST_ASSERT( lt.owns_lock() );
|
||||
BOOST_ASSERT( context::active() == lt.mutex()->owner_);
|
||||
cv_status result = cnd_.wait_for( lt, timeout_duration);
|
||||
// post-condition
|
||||
BOOST_ASSERT( lt.owns_lock() );
|
||||
BOOST_ASSERT( context::active() == lt.mutex()->owner_);
|
||||
return result;
|
||||
}
|
||||
|
||||
template< typename Rep, typename Period, typename Pred >
|
||||
bool wait_for( std::unique_lock< mutex > & lt,
|
||||
std::chrono::duration< Rep, Period > const& timeout_duration, Pred pred) {
|
||||
// pre-condition
|
||||
BOOST_ASSERT( lt.owns_lock() );
|
||||
BOOST_ASSERT( context::active() == lt.mutex()->owner_);
|
||||
bool result = cnd_.wait_for( lt, timeout_duration, pred);
|
||||
// post-condition
|
||||
BOOST_ASSERT( lt.owns_lock() );
|
||||
BOOST_ASSERT( context::active() == lt.mutex()->owner_);
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace boost {
|
||||
namespace fibers {
|
||||
|
||||
void
|
||||
condition_variable::notify_one() noexcept {
|
||||
condition_variable_any::notify_one() noexcept {
|
||||
// get one context' from wait-queue
|
||||
detail::spinlock_lock lk( wait_queue_splk_);
|
||||
if ( wait_queue_.empty() ) {
|
||||
@@ -29,7 +29,7 @@ condition_variable::notify_one() noexcept {
|
||||
}
|
||||
|
||||
void
|
||||
condition_variable::notify_all() noexcept {
|
||||
condition_variable_any::notify_all() noexcept {
|
||||
// get all context' from wait-queue
|
||||
detail::spinlock_lock lk( wait_queue_splk_);
|
||||
// notify all context'
|
||||
|
||||
Reference in New Issue
Block a user