2
0
mirror of https://github.com/boostorg/fiber.git synced 2026-02-09 23:12:57 +00:00

release mutex before signal condition-variable

This commit is contained in:
Oliver Kowalke
2015-09-05 10:36:57 +02:00
parent 983f2efb43
commit 4187c68f4e
4 changed files with 84 additions and 66 deletions

View File

@@ -96,8 +96,9 @@ private:
return queue_status::closed == state_;
}
void close_() {
void close_( std::unique_lock< boost::fibers::mutex > & lk) {
state_ = queue_status::closed;
lk.unlock();
not_empty_cond_.notify_all();
not_full_cond_.notify_all();
}
@@ -115,7 +116,7 @@ private:
}
channel_op_status push_( typename node::ptr const& new_node,
std::unique_lock< boost::fibers::mutex > & lk ) {
std::unique_lock< boost::fibers::mutex > & lk) {
if ( is_closed_() ) {
return channel_op_status::closed;
}
@@ -124,10 +125,11 @@ private:
not_full_cond_.wait( lk);
}
return push_and_notify_( new_node);
return push_and_notify_( new_node, lk);
}
channel_op_status try_push_( typename node::ptr const& new_node) {
channel_op_status try_push_( typename node::ptr const& new_node,
std::unique_lock< boost::fibers::mutex > & lk) {
if ( is_closed_() ) {
return channel_op_status::closed;
}
@@ -136,7 +138,7 @@ private:
return channel_op_status::full;
}
return push_and_notify_( new_node);
return push_and_notify_( new_node, lk);
}
template< typename Clock, typename Duration >
@@ -153,17 +155,19 @@ private:
}
}
return push_and_notify_( new_node);
return push_and_notify_( new_node, lk);
}
channel_op_status push_and_notify_( typename node::ptr const& new_node) {
channel_op_status push_and_notify_( typename node::ptr const& new_node,
std::unique_lock< boost::fibers::mutex > & lk) {
try {
push_tail_( new_node);
lk.unlock();
not_empty_cond_.notify_one();
return channel_op_status::success;
} catch (...) {
close_();
close_( lk);
throw;
}
}
@@ -174,15 +178,17 @@ private:
++count_;
}
value_type value_pop_() {
value_type value_pop_( std::unique_lock< boost::fibers::mutex > & lk) {
BOOST_ASSERT( ! is_empty_() );
try {
typename node::ptr old_head = pop_head_();
if ( size_() <= lwm_) {
if ( lwm_ == hwm_) {
lk.unlock();
not_full_cond_.notify_one();
} else {
lk.unlock();
// more than one producer could be waiting
// to push a value
not_full_cond_.notify_all();
@@ -190,7 +196,7 @@ private:
}
return std::move( old_head->va);
} catch (...) {
close_();
close_( lk);
throw;
}
}
@@ -262,7 +268,7 @@ public:
void close() {
std::unique_lock< mutex > lk( mtx_);
close_();
close_( lk);
}
channel_op_status push( value_type const& va) {
@@ -315,14 +321,14 @@ public:
typename node::ptr new_node(
new ( alloc_.allocate( 1) ) node( va, alloc_) );
std::unique_lock< mutex > lk( mtx_);
return try_push_( new_node);
return try_push_( new_node, lk);
}
channel_op_status try_push( value_type && va) {
typename node::ptr new_node(
new ( alloc_.allocate( 1) ) node( std::forward< value_type >( va), alloc_) );
std::unique_lock< mutex > lk( mtx_);
return try_push_( new_node);
return try_push_( new_node, lk);
}
channel_op_status pop( value_type & va) {
@@ -336,7 +342,7 @@ public:
return channel_op_status::closed;
}
va = value_pop_();
va = value_pop_( lk);
return channel_op_status::success;
}
@@ -351,7 +357,7 @@ public:
throw logic_error("boost fiber: queue is closed");
}
return value_pop_();
return value_pop_( lk);
}
channel_op_status try_pop( value_type & va) {
@@ -371,7 +377,7 @@ public:
return channel_op_status::empty;
}
va = value_pop_();
va = value_pop_( lk);
return channel_op_status::success;
}
@@ -397,7 +403,7 @@ public:
return channel_op_status::closed;
}
va = value_pop_();
va = value_pop_( lk);
return channel_op_status::success;
}
};

View File

@@ -43,39 +43,42 @@ private:
optional< R > value_;
std::exception_ptr except_;
void mark_ready_and_notify_() {
void mark_ready_and_notify_( std::unique_lock< mutex > & lk) {
ready_ = true;
lk.unlock();
waiters_.notify_all();
}
void owner_destroyed_() {
void owner_destroyed_( std::unique_lock< mutex > & lk) {
if ( ! ready_) {
set_exception_( std::make_exception_ptr( broken_promise() ) );
set_exception_(
std::make_exception_ptr( broken_promise() ),
lk);
}
}
void set_value_( R const& value) {
void set_value_( R const& value, std::unique_lock< mutex > & lk) {
if ( ready_) {
throw promise_already_satisfied();
}
value_ = value;
mark_ready_and_notify_();
mark_ready_and_notify_( lk);
}
void set_value_( R && value) {
void set_value_( R && value, std::unique_lock< mutex > & lk) {
if ( ready_) {
throw promise_already_satisfied();
}
value_ = std::move( value);
mark_ready_and_notify_();
mark_ready_and_notify_( lk);
}
void set_exception_( std::exception_ptr except) {
void set_exception_( std::exception_ptr except, std::unique_lock< mutex > & lk) {
if ( ready_) {
throw promise_already_satisfied();
}
except_ = except;
mark_ready_and_notify_();
mark_ready_and_notify_( lk);
}
R const& get_( std::unique_lock< mutex > & lk) {
@@ -139,22 +142,22 @@ public:
void owner_destroyed() {
std::unique_lock< mutex > lk( mtx_);
owner_destroyed_();
owner_destroyed_( lk);
}
void set_value( R const& value) {
std::unique_lock< mutex > lk( mtx_);
set_value_( value);
set_value_( value, lk);
}
void set_value( R && value) {
std::unique_lock< mutex > lk( mtx_);
set_value_( std::move( value) );
set_value_( std::move( value), lk);
}
void set_exception( std::exception_ptr except) {
std::unique_lock< mutex > lk( mtx_);
set_exception_( except);
set_exception_( except, lk);
}
R const& get() {
@@ -210,31 +213,34 @@ private:
R * value_;
std::exception_ptr except_;
void mark_ready_and_notify_() {
void mark_ready_and_notify_( std::unique_lock< mutex > & lk) {
ready_ = true;
lk.unlock();
waiters_.notify_all();
}
void owner_destroyed_() {
void owner_destroyed_( std::unique_lock< mutex > & lk) {
if ( ! ready_) {
set_exception_( std::make_exception_ptr( broken_promise() ) );
set_exception_(
std::make_exception_ptr( broken_promise() ),
lk);
}
}
void set_value_( R & value) {
void set_value_( R & value, std::unique_lock< mutex > & lk) {
if ( ready_) {
throw promise_already_satisfied();
}
value_ = & value;
mark_ready_and_notify_();
mark_ready_and_notify_( lk);
}
void set_exception_( std::exception_ptr except) {
void set_exception_( std::exception_ptr except, std::unique_lock< mutex > & lk) {
if ( ready_) {
throw promise_already_satisfied();
}
except_ = except;
mark_ready_and_notify_();
mark_ready_and_notify_( lk);
}
R & get_( std::unique_lock< mutex > & lk) {
@@ -269,7 +275,7 @@ private:
}
future_status wait_until_( std::unique_lock< mutex > & lk,
std::chrono::high_resolution_clock::time_point const& timeout_time) const {
std::chrono::high_resolution_clock::time_point const& timeout_time) const {
while ( ! ready_) {
cv_status st( waiters_.wait_until( lk, timeout_time) );
if ( cv_status::timeout == st && ! ready_) {
@@ -298,17 +304,17 @@ public:
void owner_destroyed() {
std::unique_lock< mutex > lk( mtx_);
owner_destroyed_();
owner_destroyed_( lk);
}
void set_value( R & value) {
std::unique_lock< mutex > lk( mtx_);
set_value_( value);
set_value_( value, lk);
}
void set_exception( std::exception_ptr except) {
std::unique_lock< mutex > lk( mtx_);
set_exception_( except);
set_exception_( except, lk);
}
R & get() {
@@ -364,33 +370,36 @@ private:
std::exception_ptr except_;
inline
void mark_ready_and_notify_() {
void mark_ready_and_notify_( std::unique_lock< mutex > & lk) {
ready_ = true;
lk.unlock();
waiters_.notify_all();
}
inline
void owner_destroyed_() {
void owner_destroyed_( std::unique_lock< mutex > & lk) {
if ( ! ready_) {
set_exception_( std::make_exception_ptr( broken_promise() ) );
set_exception_(
std::make_exception_ptr( broken_promise() ),
lk);
}
}
inline
void set_value_() {
void set_value_( std::unique_lock< mutex > & lk) {
if ( ready_) {
throw promise_already_satisfied();
}
mark_ready_and_notify_();
mark_ready_and_notify_( lk);
}
inline
void set_exception_( std::exception_ptr except) {
void set_exception_( std::exception_ptr except, std::unique_lock< mutex > & lk) {
if ( ready_) {
throw promise_already_satisfied();
}
except_ = except;
mark_ready_and_notify_();
mark_ready_and_notify_( lk);
}
inline
@@ -457,19 +466,19 @@ public:
inline
void owner_destroyed() {
std::unique_lock< mutex > lk( mtx_);
owner_destroyed_();
owner_destroyed_( lk);
}
inline
void set_value() {
std::unique_lock< mutex > lk( mtx_);
set_value_();
set_value_( lk);
}
inline
void set_exception( std::exception_ptr except) {
std::unique_lock< mutex > lk( mtx_);
set_exception_( except);
set_exception_( except, lk);
}
inline

View File

@@ -93,8 +93,9 @@ private:
return queue_status::closed == state_;
}
void close_() {
void close_( std::unique_lock< mutex > & lk) {
state_ = queue_status::closed;
lk.unlock();
not_empty_cond_.notify_all();
}
@@ -103,22 +104,24 @@ private:
}
channel_op_status push_( typename node::ptr const& new_node,
std::unique_lock< boost::fibers::mutex > & lk) {
std::unique_lock< mutex > & lk) {
if ( is_closed_() ) {
return channel_op_status::closed;
}
return push_and_notify_( new_node);
return push_and_notify_( new_node, lk);
}
channel_op_status push_and_notify_( typename node::ptr const& new_node) {
channel_op_status push_and_notify_( typename node::ptr const& new_node,
std::unique_lock< mutex > & lk) {
try {
push_tail_( new_node);
lk.unlock();
not_empty_cond_.notify_one();
return channel_op_status::success;
} catch (...) {
close_();
close_( lk);
throw;
}
}
@@ -128,14 +131,14 @@ private:
tail_ = & new_node->nxt;
}
value_type value_pop_() {
value_type value_pop_( std::unique_lock< mutex > & lk) {
BOOST_ASSERT( ! is_empty_() );
try {
typename node::ptr old_head = pop_head_();
return std::move( old_head->va);
} catch (...) {
close_();
close_( lk);
throw;
}
}
@@ -165,8 +168,7 @@ public:
void close() {
std::unique_lock< mutex > lk( mtx_);
close_();
close_( lk);
}
channel_op_status push( value_type const& va) {
@@ -194,7 +196,7 @@ public:
return channel_op_status::closed;
}
va = value_pop_();
va = value_pop_( lk);
return channel_op_status::success;
}
@@ -209,7 +211,7 @@ public:
throw logic_error("boost fiber: queue is closed");
}
return value_pop_();
return value_pop_( lk);
}
channel_op_status try_pop( value_type & va) {
@@ -229,19 +231,19 @@ public:
return channel_op_status::empty;
}
va = value_pop_();
va = value_pop_( lk);
return channel_op_status::success;
}
template< typename Rep, typename Period >
channel_op_status pop_wait_for( value_type & va,
std::chrono::duration< Rep, Period > const& timeout_duration) {
std::chrono::duration< Rep, Period > const& timeout_duration) {
return pop_wait_until( va, std::chrono::high_resolution_clock::now() + timeout_duration);
}
template< typename Clock, typename Duration >
channel_op_status pop_wait_until( value_type & va,
std::chrono::time_point< Clock, Duration > const& timeout_time) {
std::chrono::time_point< Clock, Duration > const& timeout_time) {
std::unique_lock< mutex > lk( mtx_);
while ( ! is_closed_() && is_empty_() ) {
@@ -253,7 +255,7 @@ public:
return channel_op_status::closed;
}
va = value_pop_();
va = value_pop_( lk);
return channel_op_status::success;
}
};

View File

@@ -36,6 +36,7 @@ barrier::wait() {
if ( 0 == --current_) {
cycle_ = ! cycle_;
current_ = initial_;
lk.unlock(); // no pessimization
cond_.notify_all();
return true;
} else {