Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:38:31

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