]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/interprocess/include/boost/interprocess/sync/detail/condition_any_algorithm.hpp
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / interprocess / include / boost / interprocess / sync / detail / condition_any_algorithm.hpp
CommitLineData
7c673cae
FG
1//////////////////////////////////////////////////////////////////////////////
2//
3// (C) Copyright Ion Gaztanaga 2012-2012. Distributed under the Boost
4// Software License, Version 1.0. (See accompanying file
5// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6//
7// See http://www.boost.org/libs/interprocess for documentation.
8//
9//////////////////////////////////////////////////////////////////////////////
10
11#ifndef BOOST_INTERPROCESS_DETAIL_CONDITION_ANY_ALGORITHM_HPP
12#define BOOST_INTERPROCESS_DETAIL_CONDITION_ANY_ALGORITHM_HPP
13
14#ifndef BOOST_CONFIG_HPP
15# include <boost/config.hpp>
16#endif
17#
18#if defined(BOOST_HAS_PRAGMA_ONCE)
19# pragma once
20#endif
21
22#include <boost/interprocess/detail/config_begin.hpp>
23#include <boost/interprocess/detail/workaround.hpp>
24#include <boost/interprocess/sync/scoped_lock.hpp>
25#include <boost/interprocess/sync/detail/locks.hpp>
26#include <limits>
27
28namespace boost {
29namespace interprocess {
30namespace ipcdetail {
31
32////////////////////////////////////////////////////////////////////////
33////////////////////////////////////////////////////////////////////////
34////////////////////////////////////////////////////////////////////////
35//
36// Condition variable 'any' (able to use any type of external mutex)
37//
38// The code is based on Howard E. Hinnant's ISO C++ N2406 paper.
39// Many thanks to Howard for his support and comments.
40////////////////////////////////////////////////////////////////////////
41////////////////////////////////////////////////////////////////////////
42////////////////////////////////////////////////////////////////////////
43
44// Required interface for ConditionAnyMembers
45// class ConditionAnyMembers
46// {
47// typedef implementation_defined mutex_type;
48// typedef implementation_defined condvar_type;
49//
50// condvar &get_condvar()
51// mutex_type &get_mutex()
52// };
53//
54// Must be initialized as following
55//
56// get_condvar() [no threads blocked]
57// get_mutex() [unlocked]
58
59template<class ConditionAnyMembers>
60class condition_any_algorithm
61{
62 private:
63 condition_any_algorithm();
64 ~condition_any_algorithm();
65 condition_any_algorithm(const condition_any_algorithm &);
66 condition_any_algorithm &operator=(const condition_any_algorithm &);
67
68 typedef typename ConditionAnyMembers::mutex_type mutex_type;
69 typedef typename ConditionAnyMembers::condvar_type condvar_type;
70
71 template <class Lock>
72 static void do_wait(ConditionAnyMembers &data, Lock& lock);
73
74 template <class Lock>
75 static bool do_timed_wait(ConditionAnyMembers &data, Lock& lock, const boost::posix_time::ptime &abs_time);
76
77 public:
78 template<class Lock>
79 static bool wait ( ConditionAnyMembers &data, Lock &mut
80 , bool timeout_enabled, const boost::posix_time::ptime &abs_time);
81 static void signal( ConditionAnyMembers &data, bool broadcast);
82};
83
84template<class ConditionAnyMembers>
85void condition_any_algorithm<ConditionAnyMembers>::signal(ConditionAnyMembers &data, bool broadcast)
86{
87 scoped_lock<mutex_type> internal_lock(data.get_mutex());
88 if(broadcast){
89 data.get_condvar().notify_all();
90 }
91 else{
92 data.get_condvar().notify_one();
93 }
94}
95
96template<class ConditionAnyMembers>
97template<class Lock>
98bool condition_any_algorithm<ConditionAnyMembers>::wait
99 ( ConditionAnyMembers &data
100 , Lock &lock
101 , bool tout_enabled
102 , const boost::posix_time::ptime &abs_time)
103{
104 if(tout_enabled){
105 return condition_any_algorithm::do_timed_wait(data, lock, abs_time);
106 }
107 else{
108 condition_any_algorithm::do_wait(data, lock);
109 return true;
110 }
111}
112
113template<class ConditionAnyMembers>
114template <class Lock>
115void condition_any_algorithm<ConditionAnyMembers>::do_wait
116 (ConditionAnyMembers &data, Lock& lock)
117{
118 //lock internal before unlocking external to avoid race with a notifier
119 scoped_lock<mutex_type> internal_lock(data.get_mutex());
120 {
121 lock_inverter<Lock> inverted_lock(lock);
122 scoped_lock<lock_inverter<Lock> > external_unlock(inverted_lock);
123 { //unlock internal first to avoid deadlock with near simultaneous waits
124 scoped_lock<mutex_type> internal_unlock;
125 internal_lock.swap(internal_unlock);
126 data.get_condvar().wait(internal_unlock);
127 }
128 }
129}
130
131template<class ConditionAnyMembers>
132template <class Lock>
133bool condition_any_algorithm<ConditionAnyMembers>::do_timed_wait
134 (ConditionAnyMembers &data, Lock& lock, const boost::posix_time::ptime &abs_time)
135{
136 //lock internal before unlocking external to avoid race with a notifier
137 scoped_lock<mutex_type> internal_lock(data.get_mutex());
138 {
139 //Unlock external lock and program for relock
140 lock_inverter<Lock> inverted_lock(lock);
141 scoped_lock<lock_inverter<Lock> > external_unlock(inverted_lock);
142 { //unlock internal first to avoid deadlock with near simultaneous waits
143 scoped_lock<mutex_type> internal_unlock;
144 internal_lock.swap(internal_unlock);
145 return data.get_condvar().timed_wait(internal_unlock, abs_time);
146 }
147 }
148}
149
150
151template<class ConditionAnyMembers>
152class condition_any_wrapper
153{
154 //Non-copyable
155 condition_any_wrapper(const condition_any_wrapper &);
156 condition_any_wrapper &operator=(const condition_any_wrapper &);
157
158 ConditionAnyMembers m_data;
159 typedef ipcdetail::condition_any_algorithm<ConditionAnyMembers> algo_type;
160
161 public:
162
163 condition_any_wrapper(){}
164
165 ~condition_any_wrapper(){}
166
167 ConditionAnyMembers & get_members()
168 { return m_data; }
169
170 const ConditionAnyMembers & get_members() const
171 { return m_data; }
172
173 void notify_one()
174 { algo_type::signal(m_data, false); }
175
176 void notify_all()
177 { algo_type::signal(m_data, true); }
178
179 template <typename L>
180 void wait(L& lock)
181 {
182 if (!lock)
183 throw lock_exception();
184 algo_type::wait(m_data, lock, false, boost::posix_time::ptime());
185 }
186
187 template <typename L, typename Pr>
188 void wait(L& lock, Pr pred)
189 {
190 if (!lock)
191 throw lock_exception();
192
193 while (!pred())
194 algo_type::wait(m_data, lock, false, boost::posix_time::ptime());
195 }
196
197 template <typename L>
198 bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time)
199 {
200 if (!lock)
201 throw lock_exception();
202 return algo_type::wait(m_data, lock, true, abs_time);
203 }
204
205 template <typename L, typename Pr>
206 bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time, Pr pred)
207 {
208 if (!lock)
209 throw lock_exception();
210 while (!pred()){
211 if (!algo_type::wait(m_data, lock, true, abs_time))
212 return pred();
213 }
214 return true;
215 }
216};
217
218} //namespace ipcdetail
219} //namespace interprocess
220} //namespace boost
221
222#include <boost/interprocess/detail/config_end.hpp>
223
224#endif //BOOST_INTERPROCESS_DETAIL_CONDITION_ANY_ALGORITHM_HPP