1 /* 2 * Distributed under the Boost Software License, Version 1.0. 3 * (See accompanying file LICENSE_1_0.txt or copy at 4 * http://www.boost.org/LICENSE_1_0.txt) 5 * 6 * (C) Copyright 2007-2008 Anthony Williams 7 * (C) Copyright 2011-2012 Vicente J. Botet Escriba 8 * (C) Copyright 2013 Andrey Semashev 9 */ 10 /*! 11 * \file detail/condition_variables/condition_variable_any_generic.hpp 12 * 13 * \brief This header is the Boost.Sync library implementation, see the library documentation 14 * at http://www.boost.org/doc/libs/release/libs/sync/doc/html/index.html. 15 */ 16 17 #ifndef BOOST_SYNC_DETAIL_CONDITION_VARIABLES_CONDITION_VARIABLE_ANY_GENERIC_HPP_INCLUDED_ 18 #define BOOST_SYNC_DETAIL_CONDITION_VARIABLES_CONDITION_VARIABLE_ANY_GENERIC_HPP_INCLUDED_ 19 20 #include <cstddef> 21 #include <boost/utility/enable_if.hpp> 22 #include <boost/sync/detail/config.hpp> 23 #include <boost/sync/detail/time_traits.hpp> 24 #include <boost/sync/locks/lock_guard.hpp> 25 #include <boost/sync/locks/unique_lock.hpp> 26 #include <boost/sync/mutexes/mutex.hpp> 27 #include <boost/sync/condition_variables/condition_variable.hpp> 28 #include <boost/sync/condition_variables/cv_status.hpp> 29 #include <boost/sync/detail/header.hpp> 30 31 #ifdef BOOST_HAS_PRAGMA_ONCE 32 #pragma once 33 #endif 34 35 namespace boost { 36 37 namespace sync { 38 39 BOOST_SYNC_DETAIL_OPEN_ABI_NAMESPACE { 40 41 class condition_variable_any 42 { 43 private: 44 template< typename Lock > 45 class relocker 46 { 47 private: 48 Lock* m_lock; 49 50 public: 51 relocker() : m_lock(NULL) {} 52 53 ~relocker() BOOST_NOEXCEPT_IF(false) 54 { 55 if (m_lock) 56 m_lock->lock(); 57 } 58 59 void unlock(Lock& lock) 60 { 61 lock.unlock(); 62 m_lock = &lock; 63 } 64 }; 65 66 private: 67 sync::mutex m_mutex; 68 sync::condition_variable m_cond; 69 70 public: 71 #if defined(BOOST_SYNC_DEFINES_MUTEX_CONSTEXPR_CONSTRUCTOR) && defined(BOOST_SYNC_DEFINES_CONDITION_VARIABLE_CONSTEXPR_CONSTRUCTOR) 72 #define BOOST_SYNC_DEFINES_CONDITION_VARIABLE_ANY_CONSTEXPR_CONSTRUCTOR 73 BOOST_DEFAULTED_FUNCTION(BOOST_CONSTEXPR condition_variable_any() BOOST_NOEXCEPT, {}) 74 #else 75 BOOST_DEFAULTED_FUNCTION(condition_variable_any(), {}) 76 #endif 77 78 void notify_one() 79 { 80 sync::lock_guard< sync::mutex > internal_lock(m_mutex); 81 m_cond.notify_one(); 82 } 83 84 void notify_all() 85 { 86 sync::lock_guard< sync::mutex > internal_lock(m_mutex); 87 m_cond.notify_all(); 88 } 89 90 template< typename Lock > 91 void wait(Lock& lock) 92 { 93 relocker< Lock > relock_guard; 94 sync::unique_lock< sync::mutex > internal_lock(m_mutex); 95 relock_guard.unlock(lock); 96 m_cond.wait(internal_lock); 97 } 98 99 template< typename Lock, typename Predicate > 100 void wait(Lock& lock, Predicate pred) 101 { 102 while (!pred()) 103 this->wait(lock); 104 } 105 106 template< typename Lock, typename Time > 107 typename enable_if_c< sync::detail::time_traits< Time >::is_specialized, bool >::type 108 timed_wait(Lock& lock, Time const& t) 109 { 110 relocker< Lock > relock_guard; 111 sync::unique_lock< sync::mutex > internal_lock(m_mutex); 112 relock_guard.unlock(lock); 113 return m_cond.timed_wait(internal_lock, t); 114 } 115 116 template< typename Lock, typename Time, typename Predicate > 117 typename enable_if_c< sync::detail::time_traits< Time >::is_specialized, bool >::type 118 timed_wait(Lock& lock, Time const& t, Predicate pred) 119 { 120 while (!pred()) 121 { 122 if (!this->timed_wait(lock, t)) 123 return pred(); 124 } 125 return true; 126 } 127 128 template< typename Lock, typename TimePoint > 129 typename detail::enable_if_tag< TimePoint, detail::time_point_tag, sync::cv_status >::type 130 wait_until(Lock& lock, TimePoint const& abs_time) 131 { 132 relocker< Lock > relock_guard; 133 sync::unique_lock< sync::mutex > internal_lock(m_mutex); 134 relock_guard.unlock(lock); 135 return m_cond.wait_until(internal_lock, abs_time); 136 } 137 138 template< typename Lock, typename TimePoint, typename Predicate > 139 typename detail::enable_if_tag< TimePoint, detail::time_point_tag, bool >::type 140 wait_until(Lock& lock, TimePoint const& abs_time, Predicate pred) 141 { 142 while (!pred()) 143 { 144 if (this->wait_until(lock, abs_time) != sync::cv_status::no_timeout) 145 return pred(); 146 } 147 return true; 148 } 149 150 template< typename Lock, typename Duration > 151 typename detail::enable_if_tag< Duration, detail::time_duration_tag, sync::cv_status >::type 152 wait_for(Lock& lock, Duration const& rel_time) 153 { 154 relocker< Lock > relock_guard; 155 sync::unique_lock< sync::mutex > internal_lock(m_mutex); 156 relock_guard.unlock(lock); 157 return m_cond.wait_for(internal_lock, rel_time); 158 } 159 160 template< typename Lock, typename Duration, typename Predicate > 161 typename detail::enable_if_tag< Duration, detail::time_duration_tag, bool >::type 162 wait_for(Lock& lock, Duration const& rel_time, Predicate pred) 163 { 164 while (!pred()) 165 { 166 if (this->wait_for(lock, rel_time) != sync::cv_status::no_timeout) 167 return pred(); 168 } 169 return true; 170 } 171 172 BOOST_DELETED_FUNCTION(condition_variable_any(condition_variable_any const&)) 173 BOOST_DELETED_FUNCTION(condition_variable_any& operator= (condition_variable_any const&)) 174 }; 175 176 } // namespace abi 177 178 } // namespace sync 179 180 } // namespace boost 181 182 #include <boost/sync/detail/footer.hpp> 183 184 #endif // BOOST_SYNC_DETAIL_CONDITION_VARIABLES_CONDITION_VARIABLE_ANY_GENERIC_HPP_INCLUDED_ 185