Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-20 07:55:21

0001 //////////////////////////////////////////////////////////////////////////////
0002 //
0003 // (C) Copyright Ion Gaztanaga 2012-2012. Distributed under the Boost
0004 // Software License, Version 1.0. (See accompanying file
0005 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0006 //
0007 // See http://www.boost.org/libs/interprocess for documentation.
0008 //
0009 //////////////////////////////////////////////////////////////////////////////
0010 
0011 #ifndef BOOST_INTERPROCESS_DETAIL_CONDITION_ANY_ALGORITHM_HPP
0012 #define BOOST_INTERPROCESS_DETAIL_CONDITION_ANY_ALGORITHM_HPP
0013 
0014 #ifndef BOOST_CONFIG_HPP
0015 #  include <boost/config.hpp>
0016 #endif
0017 0018 ">#
0019 #if defined(BOOST_HAS_PRAGMA_ONCE)
0020 #  pragma once
0021 #endif
0022 
0023 #include <boost/interprocess/detail/config_begin.hpp>
0024 #include <boost/interprocess/detail/workaround.hpp>
0025 #include <boost/interprocess/sync/scoped_lock.hpp>
0026 #include <boost/interprocess/sync/detail/locks.hpp>
0027 #include <limits>
0028 
0029 namespace boost {
0030 namespace interprocess {
0031 namespace ipcdetail {
0032 
0033 ////////////////////////////////////////////////////////////////////////
0034 ////////////////////////////////////////////////////////////////////////
0035 ////////////////////////////////////////////////////////////////////////
0036 //
0037 // Condition variable 'any' (able to use any type of external mutex)
0038 //
0039 // The code is based on Howard E. Hinnant's ISO C++ N2406 paper.
0040 // Many thanks to Howard for his support and comments.
0041 ////////////////////////////////////////////////////////////////////////
0042 ////////////////////////////////////////////////////////////////////////
0043 ////////////////////////////////////////////////////////////////////////
0044 
0045 // Required interface for ConditionAnyMembers
0046 // class ConditionAnyMembers
0047 // {
0048 //    typedef implementation_defined mutex_type;
0049 //    typedef implementation_defined condvar_type;
0050 //
0051 //    condvar     &get_condvar()
0052 //    mutex_type  &get_mutex()
0053 // };
0054 //
0055 // Must be initialized as following
0056 //
0057 //    get_condvar()  [no threads blocked]
0058 //    get_mutex()    [unlocked]
0059 
0060 template<class ConditionAnyMembers>
0061 class condition_any_algorithm
0062 {
0063    private:
0064    condition_any_algorithm();
0065    ~condition_any_algorithm();
0066    condition_any_algorithm(const condition_any_algorithm &);
0067    condition_any_algorithm &operator=(const condition_any_algorithm &);
0068 
0069    typedef typename ConditionAnyMembers::mutex_type      mutex_type;
0070    typedef typename ConditionAnyMembers::condvar_type    condvar_type;
0071 
0072    public:
0073    template <class Lock>
0074    static void wait(ConditionAnyMembers& data, Lock& lock)
0075    {
0076       //lock internal before unlocking external to avoid race with a notifier
0077       scoped_lock<mutex_type> internal_lock(data.get_mutex());
0078       {
0079          lock_inverter<Lock> inverted_lock(lock);
0080          scoped_lock<lock_inverter<Lock> >   external_unlock(inverted_lock);
0081          {  //unlock internal first to avoid deadlock with near simultaneous waits
0082             scoped_lock<mutex_type>     internal_unlock;
0083             internal_lock.swap(internal_unlock);
0084             data.get_condvar().wait(internal_unlock);
0085          }
0086       }
0087    }
0088 
0089    template <class Lock, class TimePoint>
0090    static bool timed_wait(ConditionAnyMembers &data, Lock& lock, const TimePoint &abs_time)
0091    {
0092       //lock internal before unlocking external to avoid race with a notifier
0093       scoped_lock<mutex_type> internal_lock(data.get_mutex());
0094       {
0095          //Unlock external lock and program for relock
0096          lock_inverter<Lock> inverted_lock(lock);
0097          scoped_lock<lock_inverter<Lock> >   external_unlock(inverted_lock);
0098          {  //unlock internal first to avoid deadlock with near simultaneous waits
0099             scoped_lock<mutex_type> internal_unlock;
0100             internal_lock.swap(internal_unlock);
0101             return data.get_condvar().timed_wait(internal_unlock, abs_time);
0102          }
0103       }
0104    }
0105 
0106    static void signal(ConditionAnyMembers& data, bool broadcast)
0107    {
0108       scoped_lock<mutex_type> internal_lock(data.get_mutex());
0109       if(broadcast){
0110          data.get_condvar().notify_all();
0111       }
0112       else{
0113          data.get_condvar().notify_one();
0114       }
0115    }
0116 };
0117 
0118 
0119 template<class ConditionAnyMembers>
0120 class condition_any_wrapper
0121 {
0122    //Non-copyable
0123    condition_any_wrapper(const condition_any_wrapper &);
0124    condition_any_wrapper &operator=(const condition_any_wrapper &);
0125 
0126    ConditionAnyMembers m_data;
0127    typedef ipcdetail::condition_any_algorithm<ConditionAnyMembers> algo_type;
0128 
0129    public:
0130 
0131    condition_any_wrapper(){}
0132 
0133    ~condition_any_wrapper(){}
0134 
0135    ConditionAnyMembers & get_members()
0136    {  return m_data; }
0137 
0138    const ConditionAnyMembers & get_members() const
0139    {  return m_data; }
0140 
0141    void notify_one()
0142    {  algo_type::signal(m_data, false);  }
0143 
0144    void notify_all()
0145    {  algo_type::signal(m_data, true);  }
0146 
0147    template <typename Lock>
0148    void wait(Lock& lock)
0149    {
0150       if (!lock)
0151          throw lock_exception();
0152       algo_type::wait(m_data, lock);
0153    }
0154 
0155    template <typename L, typename Pr>
0156    void wait(L& lock, Pr pred)
0157    {
0158       if (!lock)
0159          throw lock_exception();
0160 
0161       while (!pred())
0162          algo_type::wait(m_data, lock);
0163    }
0164 
0165    template <typename L, typename TimePoint>
0166    bool timed_wait(L& lock, const TimePoint &abs_time)
0167    {
0168       if (!lock)
0169          throw lock_exception();
0170       return algo_type::timed_wait(m_data, lock, abs_time);
0171    }
0172 
0173    template <typename L, typename TimePoint, typename Pr>
0174    bool timed_wait(L& lock, const TimePoint &abs_time, Pr pred)
0175    {
0176       if (!lock)
0177             throw lock_exception();
0178       while (!pred()){
0179          if (!algo_type::timed_wait(m_data, lock, abs_time))
0180             return pred();
0181       }
0182       return true;
0183    }
0184 };
0185 
0186 }  //namespace ipcdetail
0187 }  //namespace interprocess
0188 }  //namespace boost
0189 
0190 #include <boost/interprocess/detail/config_end.hpp>
0191 
0192 #endif   //BOOST_INTERPROCESS_DETAIL_CONDITION_ANY_ALGORITHM_HPP