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 public:
72 template <class Lock>
73 static void wait(ConditionAnyMembers& data, Lock& lock)
74 {
75 //lock internal before unlocking external to avoid race with a notifier
76 scoped_lock<mutex_type> internal_lock(data.get_mutex());
77 {
78 lock_inverter<Lock> inverted_lock(lock);
79 scoped_lock<lock_inverter<Lock> > external_unlock(inverted_lock);
80 { //unlock internal first to avoid deadlock with near simultaneous waits
81 scoped_lock<mutex_type> internal_unlock;
82 internal_lock.swap(internal_unlock);
83 data.get_condvar().wait(internal_unlock);
84 }
85 }
86 }
87
88 template <class Lock, class TimePoint>
89 static bool timed_wait(ConditionAnyMembers &data, Lock& lock, const TimePoint &abs_time)
90 {
91 //lock internal before unlocking external to avoid race with a notifier
92 scoped_lock<mutex_type> internal_lock(data.get_mutex());
93 {
94 //Unlock external lock and program for relock
95 lock_inverter<Lock> inverted_lock(lock);
96 scoped_lock<lock_inverter<Lock> > external_unlock(inverted_lock);
97 { //unlock internal first to avoid deadlock with near simultaneous waits
98 scoped_lock<mutex_type> internal_unlock;
99 internal_lock.swap(internal_unlock);
100 return data.get_condvar().timed_wait(internal_unlock, abs_time);
101 }
102 }
103 }
104
105 static void signal(ConditionAnyMembers& data, bool broadcast)
106 {
107 scoped_lock<mutex_type> internal_lock(data.get_mutex());
108 if(broadcast){
109 data.get_condvar().notify_all();
110 }
111 else{
112 data.get_condvar().notify_one();
113 }
114 }
115};
116
117
118template<class ConditionAnyMembers>
119class condition_any_wrapper
120{
121 //Non-copyable
122 condition_any_wrapper(const condition_any_wrapper &);
123 condition_any_wrapper &operator=(const condition_any_wrapper &);
124
125 ConditionAnyMembers m_data;
126 typedef ipcdetail::condition_any_algorithm<ConditionAnyMembers> algo_type;
127
128 public:
129
130 condition_any_wrapper(){}
131
132 ~condition_any_wrapper(){}
133
134 ConditionAnyMembers & get_members()
135 { return m_data; }
136
137 const ConditionAnyMembers & get_members() const
138 { return m_data; }
139
140 void notify_one()
141 { algo_type::signal(m_data, false); }
142
143 void notify_all()
144 { algo_type::signal(m_data, true); }
145
146 template <typename Lock>
147 void wait(Lock& lock)
148 {
149 if (!lock)
150 throw lock_exception();
151 algo_type::wait(m_data, lock);
152 }
153
154 template <typename L, typename Pr>
155 void wait(L& lock, Pr pred)
156 {
157 if (!lock)
158 throw lock_exception();
159
160 while (!pred())
161 algo_type::wait(m_data, lock);
162 }
163
164 template <typename L, typename TimePoint>
165 bool timed_wait(L& lock, const TimePoint &abs_time)
166 {
167 if (!lock)
168 throw lock_exception();
169 return algo_type::timed_wait(m_data, lock, abs_time);
170 }
171
172 template <typename L, typename TimePoint, typename Pr>
173 bool timed_wait(L& lock, const TimePoint &abs_time, Pr pred)
174 {
175 if (!lock)
176 throw lock_exception();
177 while (!pred()){
178 if (!algo_type::timed_wait(m_data, lock, abs_time))
179 return pred();
180 }
181 return true;
182 }
183};
184
185} //namespace ipcdetail
186} //namespace interprocess
187} //namespace boost
188
189#include <boost/interprocess/detail/config_end.hpp>
190
191#endif //BOOST_INTERPROCESS_DETAIL_CONDITION_ANY_ALGORITHM_HPP
192

Provided by KDAB

Privacy Policy
Improve your Profiling and Debugging skills
Find out more

source code of boost/libs/interprocess/include/boost/interprocess/sync/detail/condition_any_algorithm.hpp