1#ifndef BOOST_THREAD_PTHREAD_MUTEX_HPP
2#define BOOST_THREAD_PTHREAD_MUTEX_HPP
3// (C) Copyright 2007-8 Anthony Williams
4// (C) Copyright 2011,2012,2015 Vicente J. Botet Escriba
5// Distributed under the Boost Software License, Version 1.0. (See
6// accompanying file LICENSE_1_0.txt or copy at
7// http://www.boost.org/LICENSE_1_0.txt)
8
9#include <boost/thread/detail/config.hpp>
10#include <boost/assert.hpp>
11#include <pthread.h>
12#include <boost/throw_exception.hpp>
13#include <boost/core/ignore_unused.hpp>
14#include <boost/thread/exceptions.hpp>
15#if defined BOOST_THREAD_PROVIDES_NESTED_LOCKS
16#include <boost/thread/lock_types.hpp>
17#endif
18#include <boost/thread/thread_time.hpp>
19#if defined BOOST_THREAD_USES_DATETIME
20#include <boost/thread/xtime.hpp>
21#endif
22#include <boost/assert.hpp>
23#include <errno.h>
24#include <boost/thread/detail/platform_time.hpp>
25#include <boost/thread/pthread/pthread_mutex_scoped_lock.hpp>
26#include <boost/thread/pthread/pthread_helpers.hpp>
27#ifdef BOOST_THREAD_USES_CHRONO
28#include <boost/chrono/system_clocks.hpp>
29#include <boost/chrono/ceil.hpp>
30#endif
31#include <boost/thread/detail/delete.hpp>
32
33
34#include <boost/config/abi_prefix.hpp>
35
36namespace boost
37{
38
39 class BOOST_THREAD_CAPABILITY("mutex") mutex
40 {
41 private:
42 pthread_mutex_t m;
43 public:
44 BOOST_THREAD_NO_COPYABLE(mutex)
45
46 mutex()
47 {
48 int const res=posix::pthread_mutex_init(m: &m);
49 if(res)
50 {
51 boost::throw_exception(e: thread_resource_error(res, "boost:: mutex constructor failed in pthread_mutex_init"));
52 }
53 }
54 ~mutex()
55 {
56 BOOST_VERIFY(!posix::pthread_mutex_destroy(&m));
57 }
58
59 void lock() BOOST_THREAD_ACQUIRE()
60 {
61 int res = posix::pthread_mutex_lock(m: &m);
62 if (res)
63 {
64 boost::throw_exception(e: lock_error(res,"boost: mutex lock failed in pthread_mutex_lock"));
65 }
66 }
67
68 void unlock() BOOST_THREAD_RELEASE()
69 {
70 BOOST_VERIFY(!posix::pthread_mutex_unlock(&m));
71 }
72
73 bool try_lock() BOOST_THREAD_TRY_ACQUIRE(true)
74 {
75 int res = posix::pthread_mutex_trylock(m: &m);
76 if (res==EBUSY)
77 {
78 return false;
79 }
80
81 return !res;
82 }
83
84#define BOOST_THREAD_DEFINES_MUTEX_NATIVE_HANDLE
85 typedef pthread_mutex_t* native_handle_type;
86 native_handle_type native_handle()
87 {
88 return &m;
89 }
90
91#if defined BOOST_THREAD_PROVIDES_NESTED_LOCKS
92 typedef unique_lock<mutex> scoped_lock;
93 typedef detail::try_lock_wrapper<mutex> scoped_try_lock;
94#endif
95 };
96
97 typedef mutex try_mutex;
98
99 class timed_mutex
100 {
101 private:
102 pthread_mutex_t m;
103#ifndef BOOST_THREAD_USES_PTHREAD_TIMEDLOCK
104 pthread_cond_t cond;
105 bool is_locked;
106#endif
107 public:
108 BOOST_THREAD_NO_COPYABLE(timed_mutex)
109 timed_mutex()
110 {
111 int const res=posix::pthread_mutex_init(m: &m);
112 if(res)
113 {
114 boost::throw_exception(e: thread_resource_error(res, "boost:: timed_mutex constructor failed in pthread_mutex_init"));
115 }
116#ifndef BOOST_THREAD_USES_PTHREAD_TIMEDLOCK
117 int const res2=posix::pthread_cond_init(c: &cond);
118 if(res2)
119 {
120 BOOST_VERIFY(!posix::pthread_mutex_destroy(&m));
121 boost::throw_exception(e: thread_resource_error(res2, "boost:: timed_mutex constructor failed in pthread_cond_init"));
122 }
123 is_locked=false;
124#endif
125 }
126 ~timed_mutex()
127 {
128 BOOST_VERIFY(!posix::pthread_mutex_destroy(&m));
129#ifndef BOOST_THREAD_USES_PTHREAD_TIMEDLOCK
130 BOOST_VERIFY(!posix::pthread_cond_destroy(&cond));
131#endif
132 }
133
134#if defined BOOST_THREAD_USES_DATETIME
135 template<typename TimeDuration>
136 bool timed_lock(TimeDuration const & relative_time)
137 {
138 if (relative_time.is_pos_infinity())
139 {
140 lock();
141 return true;
142 }
143 if (relative_time.is_special())
144 {
145 return true;
146 }
147 detail::platform_duration d(relative_time);
148#if defined(BOOST_THREAD_HAS_MONO_CLOCK) && !defined(BOOST_THREAD_INTERNAL_CLOCK_IS_MONO)
149 const detail::mono_platform_timepoint ts(detail::mono_platform_clock::now() + d);
150 d = (std::min)(d, detail::platform_milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS));
151 while ( ! do_try_lock_until(detail::internal_platform_clock::now() + d) )
152 {
153 d = ts - detail::mono_platform_clock::now();
154 if ( d <= detail::platform_duration::zero() ) return false; // timeout occurred
155 d = (std::min)(d, detail::platform_milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS));
156 }
157 return true;
158#else
159 return do_try_lock_until(timeout: detail::internal_platform_clock::now() + d);
160#endif
161 }
162 bool timed_lock(boost::xtime const & absolute_time)
163 {
164 return timed_lock(abs_time: system_time(absolute_time));
165 }
166#endif
167#ifdef BOOST_THREAD_USES_PTHREAD_TIMEDLOCK
168 void lock()
169 {
170 int res = posix::pthread_mutex_lock(&m);
171 if (res)
172 {
173 boost::throw_exception(lock_error(res,"boost: mutex lock failed in pthread_mutex_lock"));
174 }
175 }
176
177 void unlock()
178 {
179 BOOST_VERIFY(!posix::pthread_mutex_unlock(&m));
180 }
181
182 bool try_lock()
183 {
184 int res = posix::pthread_mutex_trylock(&m);
185 if (res==EBUSY)
186 {
187 return false;
188 }
189
190 return !res;
191 }
192
193
194 private:
195 bool do_try_lock_until(detail::internal_platform_timepoint const &timeout)
196 {
197 int const res=pthread_mutex_timedlock(&m,&timeout.getTs());
198 BOOST_ASSERT(!res || res==ETIMEDOUT);
199 return !res;
200 }
201 public:
202
203#else
204 void lock()
205 {
206 boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
207 while(is_locked)
208 {
209 BOOST_VERIFY(!posix::pthread_cond_wait(&cond,&m));
210 }
211 is_locked=true;
212 }
213
214 void unlock()
215 {
216 boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
217 is_locked=false;
218 BOOST_VERIFY(!posix::pthread_cond_signal(&cond));
219 }
220
221 bool try_lock()
222 {
223 boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
224 if(is_locked)
225 {
226 return false;
227 }
228 is_locked=true;
229 return true;
230 }
231
232 private:
233 bool do_try_lock_until(detail::internal_platform_timepoint const &timeout)
234 {
235 boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
236 while(is_locked)
237 {
238 int const cond_res=posix::pthread_cond_timedwait(c: &cond,m: &m,t: &timeout.getTs());
239 if(cond_res==ETIMEDOUT)
240 {
241 break;
242 }
243 BOOST_ASSERT(!cond_res);
244 }
245 if(is_locked)
246 {
247 return false;
248 }
249 is_locked=true;
250 return true;
251 }
252 public:
253#endif
254
255#if defined BOOST_THREAD_USES_DATETIME
256 bool timed_lock(system_time const & abs_time)
257 {
258 const detail::real_platform_timepoint ts(abs_time);
259#if defined BOOST_THREAD_INTERNAL_CLOCK_IS_MONO
260 detail::platform_duration d(ts - detail::real_platform_clock::now());
261 d = (std::min)(a: d, b: detail::platform_milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS));
262 while ( ! do_try_lock_until(timeout: detail::internal_platform_clock::now() + d) )
263 {
264 d = ts - detail::real_platform_clock::now();
265 if ( d <= detail::platform_duration::zero() ) return false; // timeout occurred
266 d = (std::min)(a: d, b: detail::platform_milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS));
267 }
268 return true;
269#else
270 return do_try_lock_until(ts);
271#endif
272 }
273#endif
274#ifdef BOOST_THREAD_USES_CHRONO
275 template <class Rep, class Period>
276 bool try_lock_for(const chrono::duration<Rep, Period>& rel_time)
277 {
278 return try_lock_until(chrono::steady_clock::now() + rel_time);
279 }
280 template <class Clock, class Duration>
281 bool try_lock_until(const chrono::time_point<Clock, Duration>& t)
282 {
283 typedef typename common_type<Duration, typename Clock::duration>::type common_duration;
284 common_duration d(t - Clock::now());
285 d = (std::min)(d, common_duration(chrono::milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS)));
286 while ( ! try_lock_until(detail::internal_chrono_clock::now() + d))
287 {
288 d = t - Clock::now();
289 if ( d <= common_duration::zero() ) return false; // timeout occurred
290 d = (std::min)(d, common_duration(chrono::milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS)));
291 }
292 return true;
293 }
294 template <class Duration>
295 bool try_lock_until(const chrono::time_point<detail::internal_chrono_clock, Duration>& t)
296 {
297 detail::internal_platform_timepoint ts(t);
298 return do_try_lock_until(timeout: ts);
299 }
300#endif
301
302#define BOOST_THREAD_DEFINES_TIMED_MUTEX_NATIVE_HANDLE
303 typedef pthread_mutex_t* native_handle_type;
304 native_handle_type native_handle()
305 {
306 return &m;
307 }
308
309#if defined BOOST_THREAD_PROVIDES_NESTED_LOCKS
310 typedef unique_lock<timed_mutex> scoped_timed_lock;
311 typedef detail::try_lock_wrapper<timed_mutex> scoped_try_lock;
312 typedef scoped_timed_lock scoped_lock;
313#endif
314 };
315}
316
317#include <boost/config/abi_suffix.hpp>
318
319
320#endif
321

source code of boost/libs/thread/include/boost/thread/pthread/mutex.hpp