typedef typename ConditionMembers::integer_type integer_type;
public:
- template<class Lock>
- static bool wait ( ConditionMembers &data, Lock &lock
- , bool timeout_enabled, const boost::posix_time::ptime &abs_time);
- static void signal(ConditionMembers &data, bool broadcast);
-};
-
-template<class ConditionMembers>
-inline void condition_algorithm_8a<ConditionMembers>::signal(ConditionMembers &data, bool broadcast)
-{
- integer_type nsignals_to_issue;
-
+ template<bool TimeoutEnabled, class Lock, class TimePoint>
+ static bool wait ( ConditionMembers &data, Lock &lock, const TimePoint &abs_time)
{
- scoped_lock<mutex_type> locker(data.get_mtx_unblock_lock());
-
- if ( 0 != data.get_nwaiters_to_unblock() ) { // the gate is closed!!!
- if ( 0 == data.get_nwaiters_blocked() ) { // NO-OP
- //locker's destructor triggers data.get_mtx_unblock_lock().unlock()
- return;
- }
- if (broadcast) {
- data.get_nwaiters_to_unblock() += nsignals_to_issue = data.get_nwaiters_blocked();
- data.get_nwaiters_blocked() = 0;
- }
- else {
- nsignals_to_issue = 1;
- data.get_nwaiters_to_unblock()++;
- data.get_nwaiters_blocked()--;
+ //Initialize to avoid warnings
+ integer_type nsignals_was_left = 0;
+ integer_type nwaiters_was_gone = 0;
+
+ data.get_sem_block_lock().wait();
+ ++data.get_nwaiters_blocked();
+ data.get_sem_block_lock().post();
+
+ //Unlock external lock and program for relock
+ lock_inverter<Lock> inverted_lock(lock);
+ scoped_lock<lock_inverter<Lock> > external_unlock(inverted_lock);
+
+ bool bTimedOut = !do_sem_timed_wait(data.get_sem_block_queue(), abs_time, bool_<TimeoutEnabled>());
+
+ {
+ scoped_lock<mutex_type> locker(data.get_mtx_unblock_lock());
+ if ( 0 != (nsignals_was_left = data.get_nwaiters_to_unblock()) ) {
+ if ( bTimedOut ) { // timeout (or canceled)
+ if ( 0 != data.get_nwaiters_blocked() ) {
+ data.get_nwaiters_blocked()--;
+ }
+ else {
+ data.get_nwaiters_gone()++; // count spurious wakeups.
+ }
+ }
+ if ( 0 == --data.get_nwaiters_to_unblock() ) {
+ if ( 0 != data.get_nwaiters_blocked() ) {
+ data.get_sem_block_lock().post(); // open the gate.
+ nsignals_was_left = 0; // do not open the gate below again.
+ }
+ else if ( 0 != (nwaiters_was_gone = data.get_nwaiters_gone()) ) {
+ data.get_nwaiters_gone() = 0;
+ }
+ }
}
- }
- else if ( data.get_nwaiters_blocked() > data.get_nwaiters_gone() ) { // HARMLESS RACE CONDITION!
- data.get_sem_block_lock().wait(); // close the gate
- if ( 0 != data.get_nwaiters_gone() ) {
- data.get_nwaiters_blocked() -= data.get_nwaiters_gone();
+ else if ( (std::numeric_limits<integer_type>::max)()/2
+ == ++data.get_nwaiters_gone() ) { // timeout/canceled or spurious semaphore :-)
+ data.get_sem_block_lock().wait();
+ data.get_nwaiters_blocked() -= data.get_nwaiters_gone(); // something is going on here - test of timeouts? :-)
+ data.get_sem_block_lock().post();
data.get_nwaiters_gone() = 0;
}
- if (broadcast) {
- nsignals_to_issue = data.get_nwaiters_to_unblock() = data.get_nwaiters_blocked();
- data.get_nwaiters_blocked() = 0;
- }
- else {
- nsignals_to_issue = data.get_nwaiters_to_unblock() = 1;
- data.get_nwaiters_blocked()--;
- }
- }
- else { // NO-OP
//locker's destructor triggers data.get_mtx_unblock_lock().unlock()
- return;
}
- //locker's destructor triggers data.get_mtx_unblock_lock().unlock()
- }
- data.get_sem_block_queue().post(nsignals_to_issue);
-}
-template<class ConditionMembers>
-template<class Lock>
-inline bool condition_algorithm_8a<ConditionMembers>::wait
- ( ConditionMembers &data
- , Lock &lock
- , bool tout_enabled
- , const boost::posix_time::ptime &abs_time
- )
-{
- //Initialize to avoid warnings
- integer_type nsignals_was_left = 0;
- integer_type nwaiters_was_gone = 0;
-
- data.get_sem_block_lock().wait();
- ++data.get_nwaiters_blocked();
- data.get_sem_block_lock().post();
+ if ( 1 == nsignals_was_left ) {
+ if ( 0 != nwaiters_was_gone ) {
+ // sem_adjust( data.get_sem_block_queue(),-nwaiters_was_gone );
+ while ( nwaiters_was_gone-- ) {
+ data.get_sem_block_queue().wait(); // better now than spurious later
+ }
+ }
+ data.get_sem_block_lock().post(); // open the gate
+ }
- //Unlock external lock and program for relock
- lock_inverter<Lock> inverted_lock(lock);
- scoped_lock<lock_inverter<Lock> > external_unlock(inverted_lock);
+ //lock.lock(); called from unlocker destructor
- bool bTimedOut = tout_enabled
- ? !data.get_sem_block_queue().timed_wait(abs_time)
- : (data.get_sem_block_queue().wait(), false);
+ return ( bTimedOut ) ? false : true;
+ }
+ static void signal(ConditionMembers &data, bool broadcast)
{
- scoped_lock<mutex_type> locker(data.get_mtx_unblock_lock());
- if ( 0 != (nsignals_was_left = data.get_nwaiters_to_unblock()) ) {
- if ( bTimedOut ) { // timeout (or canceled)
- if ( 0 != data.get_nwaiters_blocked() ) {
- data.get_nwaiters_blocked()--;
+ integer_type nsignals_to_issue;
+
+ {
+ scoped_lock<mutex_type> locker(data.get_mtx_unblock_lock());
+
+ if ( 0 != data.get_nwaiters_to_unblock() ) { // the gate is closed!!!
+ if ( 0 == data.get_nwaiters_blocked() ) { // NO-OP
+ //locker's destructor triggers data.get_mtx_unblock_lock().unlock()
+ return;
+ }
+ if (broadcast) {
+ data.get_nwaiters_to_unblock() += nsignals_to_issue = data.get_nwaiters_blocked();
+ data.get_nwaiters_blocked() = 0;
}
else {
- data.get_nwaiters_gone()++; // count spurious wakeups.
+ nsignals_to_issue = 1;
+ data.get_nwaiters_to_unblock()++;
+ data.get_nwaiters_blocked()--;
}
}
- if ( 0 == --data.get_nwaiters_to_unblock() ) {
- if ( 0 != data.get_nwaiters_blocked() ) {
- data.get_sem_block_lock().post(); // open the gate.
- nsignals_was_left = 0; // do not open the gate below again.
- }
- else if ( 0 != (nwaiters_was_gone = data.get_nwaiters_gone()) ) {
+ else if ( data.get_nwaiters_blocked() > data.get_nwaiters_gone() ) { // HARMLESS RACE CONDITION!
+ data.get_sem_block_lock().wait(); // close the gate
+ if ( 0 != data.get_nwaiters_gone() ) {
+ data.get_nwaiters_blocked() -= data.get_nwaiters_gone();
data.get_nwaiters_gone() = 0;
}
+ if (broadcast) {
+ nsignals_to_issue = data.get_nwaiters_to_unblock() = data.get_nwaiters_blocked();
+ data.get_nwaiters_blocked() = 0;
+ }
+ else {
+ nsignals_to_issue = data.get_nwaiters_to_unblock() = 1;
+ data.get_nwaiters_blocked()--;
+ }
}
- }
- else if ( (std::numeric_limits<integer_type>::max)()/2
- == ++data.get_nwaiters_gone() ) { // timeout/canceled or spurious semaphore :-)
- data.get_sem_block_lock().wait();
- data.get_nwaiters_blocked() -= data.get_nwaiters_gone(); // something is going on here - test of timeouts? :-)
- data.get_sem_block_lock().post();
- data.get_nwaiters_gone() = 0;
- }
- //locker's destructor triggers data.get_mtx_unblock_lock().unlock()
- }
-
- if ( 1 == nsignals_was_left ) {
- if ( 0 != nwaiters_was_gone ) {
- // sem_adjust( data.get_sem_block_queue(),-nwaiters_was_gone );
- while ( nwaiters_was_gone-- ) {
- data.get_sem_block_queue().wait(); // better now than spurious later
+ else { // NO-OP
+ //locker's destructor triggers data.get_mtx_unblock_lock().unlock()
+ return;
}
+ //locker's destructor triggers data.get_mtx_unblock_lock().unlock()
}
- data.get_sem_block_lock().post(); // open the gate
+ data.get_sem_block_queue().post(nsignals_to_issue);
}
- //lock.lock(); called from unlocker destructor
-
- return ( bTimedOut ) ? false : true;
-}
+ private:
+ template<class TimePoint>
+ static bool do_sem_timed_wait(semaphore_type &sem, const TimePoint &abs_time, bool_<true>)
+ { return sem.timed_wait(abs_time); }
+ template<class TimePoint>
+ static bool do_sem_timed_wait(semaphore_type &sem, const TimePoint &, bool_<false>)
+ { sem.wait(); return true; }
+};
template<class ConditionMembers>
class condition_8a_wrapper
condition_8a_wrapper &operator=(const condition_8a_wrapper &);
ConditionMembers m_data;
- typedef ipcdetail::condition_algorithm_8a<ConditionMembers> algo_type;
+ typedef condition_algorithm_8a<ConditionMembers> algo_type;
public:
{
if (!lock)
throw lock_exception();
- algo_type::wait(m_data, lock, false, boost::posix_time::ptime());
+ algo_type::template wait<false>(m_data, lock, 0);
}
template <typename L, typename Pr>
throw lock_exception();
while (!pred())
- algo_type::wait(m_data, lock, false, boost::posix_time::ptime());
+ algo_type::template wait<false>(m_data, lock, 0);
}
- template <typename L>
- bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time)
+ template <typename L, class TimePoint>
+ bool timed_wait(L& lock, const TimePoint &abs_time)
{
if (!lock)
throw lock_exception();
- return algo_type::wait(m_data, lock, true, abs_time);
+ return algo_type::template wait<true>(m_data, lock, abs_time);
}
- template <typename L, typename Pr>
- bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time, Pr pred)
+ template <typename L, class TimePoint, typename Pr>
+ bool timed_wait(L& lock, const TimePoint &abs_time, Pr pred)
{
if (!lock)
throw lock_exception();
while (!pred()){
- if (!algo_type::wait(m_data, lock, true, abs_time))
+ if (!algo_type::template wait<true>(m_data, lock, abs_time))
return pred();
}
return true;