1//////////////////////////////////////////////////////////////////////////////
2//
3// (C) Copyright Ion Gaztanaga 2005-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_POSIX_CONDITION_HPP
12#define BOOST_INTERPROCESS_POSIX_CONDITION_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
25#include <boost/interprocess/sync/cv_status.hpp>
26#include <pthread.h>
27#include <errno.h>
28#include <boost/interprocess/sync/posix/pthread_helpers.hpp>
29#include <boost/interprocess/sync/posix/timepoint_to_timespec.hpp>
30#include <boost/interprocess/timed_utils.hpp>
31#include <boost/interprocess/sync/posix/mutex.hpp>
32#include <boost/assert.hpp>
33
34namespace boost {
35namespace interprocess {
36namespace ipcdetail {
37
38class posix_condition
39{
40 //Non-copyable
41 posix_condition(const posix_condition &);
42 posix_condition &operator=(const posix_condition &);
43
44 public:
45 //!Constructs a posix_condition. On error throws interprocess_exception.
46 posix_condition();
47
48 //!Destroys *this
49 //!liberating system resources.
50 ~posix_condition();
51
52 //!If there is a thread waiting on *this, change that
53 //!thread's state to ready. Otherwise there is no effect.
54 void notify_one();
55
56 //!Change the state of all threads waiting on *this to ready.
57 //!If there are no waiting threads, notify_all() has no effect.
58 void notify_all();
59
60 //!Releases the lock on the posix_mutex object associated with lock, blocks
61 //!the current thread of execution until readied by a call to
62 //!this->notify_one() or this->notify_all(), and then reacquires the lock.
63 template <typename L>
64 void wait(L& lock)
65 {
66 if (!lock)
67 throw lock_exception();
68 this->do_wait(mut&: *lock.mutex());
69 }
70
71 //!The same as:
72 //!while (!pred()) wait(lock)
73 template <typename L, typename Pr>
74 void wait(L& lock, Pr pred)
75 {
76 if (!lock)
77 throw lock_exception();
78
79 while (!pred())
80 this->do_wait(mut&: *lock.mutex());
81 }
82
83 //!Releases the lock on the posix_mutex object associated with lock, blocks
84 //!the current thread of execution until readied by a call to
85 //!this->notify_one() or this->notify_all(), or until time abs_time is reached,
86 //!and then reacquires the lock.
87 //!Returns: false if time abs_time is reached, otherwise true.
88 template <typename L, typename TimePoint>
89 bool timed_wait(L& lock, const TimePoint &abs_time)
90 {
91 if (!lock)
92 throw lock_exception();
93 //Posix does not support infinity absolute time so handle it here
94 if(ipcdetail::is_pos_infinity(abs_time)){
95 this->wait(lock);
96 return true;
97 }
98 return this->do_timed_wait(abs_time, *lock.mutex());
99 }
100
101 //!The same as: while (!pred()) {
102 //! if (!timed_wait(lock, abs_time)) return pred();
103 //! } return true;
104 template <typename L, typename TimePoint, typename Pr>
105 bool timed_wait(L& lock, const TimePoint &abs_time, Pr pred)
106 {
107 if (!lock)
108 throw lock_exception();
109 //Posix does not support infinity absolute time so handle it here
110 if(ipcdetail::is_pos_infinity(abs_time)){
111 this->wait(lock, pred);
112 return true;
113 }
114 while (!pred()){
115 if (!this->do_timed_wait(abs_time, *lock.mutex()))
116 return pred();
117 }
118 return true;
119 }
120
121 //!Same as `timed_wait`, but this function is modeled after the
122 //!standard library interface.
123 template <typename L, class TimePoint>
124 cv_status wait_until(L& lock, const TimePoint &abs_time)
125 { return this->timed_wait(lock, abs_time) ? cv_status::no_timeout : cv_status::timeout; }
126
127 //!Same as `timed_wait`, but this function is modeled after the
128 //!standard library interface.
129 template <typename L, class TimePoint, typename Pr>
130 bool wait_until(L& lock, const TimePoint &abs_time, Pr pred)
131 { return this->timed_wait(lock, abs_time, pred); }
132
133 template <typename L, class Duration>
134 cv_status wait_for(L& lock, const Duration &dur)
135 { return this->wait_until(lock, duration_to_ustime(dur)) ? cv_status::no_timeout : cv_status::timeout; }
136
137 template <typename L, class Duration, typename Pr>
138 bool wait_for(L& lock, const Duration &dur, Pr pred)
139 { return this->wait_until(lock, duration_to_ustime(dur), pred); }
140
141 void do_wait(posix_mutex &mut);
142
143 template<class TimePoint>
144 bool do_timed_wait(const TimePoint &abs_time, posix_mutex &mut);
145
146 private:
147 pthread_cond_t m_condition;
148};
149
150inline posix_condition::posix_condition()
151{
152 int res;
153 pthread_condattr_t cond_attr;
154 res = pthread_condattr_init(attr: &cond_attr);
155 if(res != 0){
156 throw interprocess_exception("pthread_condattr_init failed");
157 }
158 res = pthread_condattr_setpshared(attr: &cond_attr, PTHREAD_PROCESS_SHARED);
159 if(res != 0){
160 pthread_condattr_destroy(attr: &cond_attr);
161 throw interprocess_exception(res);
162 }
163 res = pthread_cond_init(cond: &m_condition, cond_attr: &cond_attr);
164 pthread_condattr_destroy(attr: &cond_attr);
165 if(res != 0){
166 throw interprocess_exception(res);
167 }
168}
169
170inline posix_condition::~posix_condition()
171{
172 int res = 0;
173 res = pthread_cond_destroy(cond: &m_condition);
174 BOOST_ASSERT(res == 0); (void)res;
175}
176
177inline void posix_condition::notify_one()
178{
179 int res = 0;
180 res = pthread_cond_signal(cond: &m_condition);
181 BOOST_ASSERT(res == 0); (void)res;
182}
183
184inline void posix_condition::notify_all()
185{
186 int res = 0;
187 res = pthread_cond_broadcast(cond: &m_condition);
188 BOOST_ASSERT(res == 0); (void)res;
189}
190
191inline void posix_condition::do_wait(posix_mutex &mut)
192{
193 pthread_mutex_t* pmutex = &mut.m_mut;
194 int res = 0;
195 res = pthread_cond_wait(cond: &m_condition, mutex: pmutex);
196 BOOST_ASSERT(res == 0); (void)res;
197}
198
199template<class TimePoint>
200inline bool posix_condition::do_timed_wait
201 (const TimePoint &abs_time, posix_mutex &mut)
202{
203 timespec ts = timepoint_to_timespec(abs_time);
204 pthread_mutex_t* pmutex = &mut.m_mut;
205 int res = 0;
206 res = pthread_cond_timedwait(cond: &m_condition, mutex: pmutex, abstime: &ts);
207 BOOST_ASSERT(res == 0 || res == ETIMEDOUT);
208
209 return res != ETIMEDOUT;
210}
211
212} //namespace ipcdetail
213} //namespace interprocess
214} //namespace boost
215
216#include <boost/interprocess/detail/config_end.hpp>
217
218#endif //#ifndef BOOST_INTERPROCESS_POSIX_CONDITION_HPP
219

Provided by KDAB

Privacy Policy
Update your C++ knowledge – Modern C++11/14/17 Training
Find out more

source code of boost/libs/interprocess/include/boost/interprocess/sync/posix/condition.hpp