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)
9 #include <boost/thread/detail/config.hpp>
10 #include <boost/assert.hpp>
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>
18 #include <boost/thread/thread_time.hpp>
19 #include <boost/thread/xtime.hpp>
20 #include <boost/assert.hpp>
22 #include <boost/thread/pthread/timespec.hpp>
23 #include <boost/thread/pthread/pthread_mutex_scoped_lock.hpp>
24 #ifdef BOOST_THREAD_USES_CHRONO
25 #include <boost/chrono/system_clocks.hpp>
26 #include <boost/chrono/ceil.hpp>
28 #include <boost/thread/detail/delete.hpp>
30 #if (defined(_POSIX_TIMEOUTS) && (_POSIX_TIMEOUTS-0)>=200112L) \
31 || (defined(__ANDROID__) && defined(__ANDROID_API__) && __ANDROID_API__ >= 21)
32 #ifndef BOOST_PTHREAD_HAS_TIMEDLOCK
33 #define BOOST_PTHREAD_HAS_TIMEDLOCK
38 #include <boost/config/abi_prefix.hpp>
40 #ifndef BOOST_THREAD_HAS_NO_EINTR_BUG
41 #define BOOST_THREAD_HAS_EINTR_BUG
47 #ifdef BOOST_THREAD_HAS_EINTR_BUG
48 BOOST_FORCEINLINE int pthread_mutex_destroy(pthread_mutex_t* m)
53 ret = ::pthread_mutex_destroy(m);
54 } while (ret == EINTR);
57 BOOST_FORCEINLINE int pthread_mutex_lock(pthread_mutex_t* m)
62 ret = ::pthread_mutex_lock(m);
63 } while (ret == EINTR);
66 BOOST_FORCEINLINE int pthread_mutex_unlock(pthread_mutex_t* m)
71 ret = ::pthread_mutex_unlock(m);
72 } while (ret == EINTR);
76 BOOST_FORCEINLINE int pthread_mutex_destroy(pthread_mutex_t* m)
78 return ::pthread_mutex_destroy(m);
80 BOOST_FORCEINLINE int pthread_mutex_lock(pthread_mutex_t* m)
82 return ::pthread_mutex_lock(m);
84 BOOST_FORCEINLINE int pthread_mutex_unlock(pthread_mutex_t* m)
86 return ::pthread_mutex_unlock(m);
97 BOOST_THREAD_NO_COPYABLE(mutex)
101 int const res=pthread_mutex_init(&m,NULL);
104 boost::throw_exception(thread_resource_error(res, "boost:: mutex constructor failed in pthread_mutex_init"));
109 int const res = posix::pthread_mutex_destroy(&m);
110 boost::ignore_unused(res);
116 int res = posix::pthread_mutex_lock(&m);
119 boost::throw_exception(lock_error(res,"boost: mutex lock failed in pthread_mutex_lock"));
125 int res = posix::pthread_mutex_unlock(&m);
127 BOOST_ASSERT(res == 0);
130 // boost::throw_exception(lock_error(res,"boost: mutex unlock failed in pthread_mutex_unlock"));
139 res = pthread_mutex_trylock(&m);
140 } while (res == EINTR);
149 #define BOOST_THREAD_DEFINES_MUTEX_NATIVE_HANDLE
150 typedef pthread_mutex_t* native_handle_type;
151 native_handle_type native_handle()
156 #if defined BOOST_THREAD_PROVIDES_NESTED_LOCKS
157 typedef unique_lock<mutex> scoped_lock;
158 typedef detail::try_lock_wrapper<mutex> scoped_try_lock;
162 typedef mutex try_mutex;
168 #ifndef BOOST_PTHREAD_HAS_TIMEDLOCK
173 BOOST_THREAD_NO_COPYABLE(timed_mutex)
176 int const res=pthread_mutex_init(&m,NULL);
179 boost::throw_exception(thread_resource_error(res, "boost:: timed_mutex constructor failed in pthread_mutex_init"));
181 #ifndef BOOST_PTHREAD_HAS_TIMEDLOCK
182 int const res2=pthread_cond_init(&cond,NULL);
185 BOOST_VERIFY(!posix::pthread_mutex_destroy(&m));
186 //BOOST_VERIFY(!pthread_mutex_destroy(&m));
187 boost::throw_exception(thread_resource_error(res2, "boost:: timed_mutex constructor failed in pthread_cond_init"));
194 BOOST_VERIFY(!posix::pthread_mutex_destroy(&m));
195 #ifndef BOOST_PTHREAD_HAS_TIMEDLOCK
196 BOOST_VERIFY(!pthread_cond_destroy(&cond));
200 #if defined BOOST_THREAD_USES_DATETIME
201 template<typename TimeDuration>
202 bool timed_lock(TimeDuration const & relative_time)
204 return timed_lock(get_system_time()+relative_time);
206 bool timed_lock(boost::xtime const & absolute_time)
208 return timed_lock(system_time(absolute_time));
211 #ifdef BOOST_PTHREAD_HAS_TIMEDLOCK
214 int res = posix::pthread_mutex_lock(&m);
217 boost::throw_exception(lock_error(res,"boost: mutex lock failed in pthread_mutex_lock"));
223 int res = posix::pthread_mutex_unlock(&m);
225 BOOST_ASSERT(res == 0);
228 // boost::throw_exception(lock_error(res,"boost: mutex unlock failed in pthread_mutex_unlock"));
237 res = pthread_mutex_trylock(&m);
238 } while (res == EINTR);
249 bool do_try_lock_until(struct timespec const &timeout)
251 int const res=pthread_mutex_timedlock(&m,&timeout);
252 BOOST_ASSERT(!res || res==ETIMEDOUT);
260 boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
263 BOOST_VERIFY(!pthread_cond_wait(&cond,&m));
270 boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
272 BOOST_VERIFY(!pthread_cond_signal(&cond));
277 boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
287 bool do_try_lock_until(struct timespec const &timeout)
289 boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
292 int const cond_res=pthread_cond_timedwait(&cond,&m,&timeout);
293 if(cond_res==ETIMEDOUT)
297 BOOST_ASSERT(!cond_res);
305 #if defined BOOST_THREAD_USES_DATETIME
306 bool timed_lock(system_time const & abs_time)
308 struct timespec const ts=boost::detail::to_timespec(abs_time);
309 return do_try_lock_until(ts);
312 #ifdef BOOST_THREAD_USES_CHRONO
313 template <class Rep, class Period>
314 bool try_lock_for(const chrono::duration<Rep, Period>& rel_time)
316 return try_lock_until(chrono::steady_clock::now() + rel_time);
318 template <class Clock, class Duration>
319 bool try_lock_until(const chrono::time_point<Clock, Duration>& t)
321 using namespace chrono;
322 system_clock::time_point s_now = system_clock::now();
323 typename Clock::time_point c_now = Clock::now();
324 return try_lock_until(s_now + ceil<nanoseconds>(t - c_now));
326 template <class Duration>
327 bool try_lock_until(const chrono::time_point<chrono::system_clock, Duration>& t)
329 using namespace chrono;
330 typedef time_point<system_clock, nanoseconds> nano_sys_tmpt;
331 return try_lock_until(nano_sys_tmpt(ceil<nanoseconds>(t.time_since_epoch())));
333 bool try_lock_until(const chrono::time_point<chrono::system_clock, chrono::nanoseconds>& tp)
335 //using namespace chrono;
336 chrono::nanoseconds d = tp.time_since_epoch();
337 timespec ts = boost::detail::to_timespec(d);
338 return do_try_lock_until(ts);
342 #define BOOST_THREAD_DEFINES_TIMED_MUTEX_NATIVE_HANDLE
343 typedef pthread_mutex_t* native_handle_type;
344 native_handle_type native_handle()
349 #if defined BOOST_THREAD_PROVIDES_NESTED_LOCKS
350 typedef unique_lock<timed_mutex> scoped_timed_lock;
351 typedef detail::try_lock_wrapper<timed_mutex> scoped_try_lock;
352 typedef scoped_timed_lock scoped_lock;
358 #include <boost/config/abi_suffix.hpp>