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 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>
11 #include <boost/throw_exception.hpp>
12 #include <boost/core/ignore_unused.hpp>
13 #include <boost/thread/exceptions.hpp>
14 #if defined BOOST_THREAD_PROVIDES_NESTED_LOCKS
15 #include <boost/thread/lock_types.hpp>
17 #include <boost/thread/thread_time.hpp>
18 #include <boost/thread/xtime.hpp>
19 #include <boost/assert.hpp>
21 #include <boost/thread/pthread/timespec.hpp>
22 #include <boost/thread/pthread/pthread_mutex_scoped_lock.hpp>
23 #ifdef BOOST_THREAD_USES_CHRONO
24 #include <boost/chrono/system_clocks.hpp>
25 #include <boost/chrono/ceil.hpp>
27 #include <boost/thread/detail/delete.hpp>
29 #ifdef _POSIX_TIMEOUTS
30 #if _POSIX_TIMEOUTS >= 0 && _POSIX_TIMEOUTS>=200112L
31 #ifndef BOOST_PTHREAD_HAS_TIMEDLOCK
32 #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);
128 boost::throw_exception(lock_error(res,"boost: mutex unlock failed in pthread_mutex_unlock"));
137 res = pthread_mutex_trylock(&m);
138 } while (res == EINTR);
147 #define BOOST_THREAD_DEFINES_MUTEX_NATIVE_HANDLE
148 typedef pthread_mutex_t* native_handle_type;
149 native_handle_type native_handle()
154 #if defined BOOST_THREAD_PROVIDES_NESTED_LOCKS
155 typedef unique_lock<mutex> scoped_lock;
156 typedef detail::try_lock_wrapper<mutex> scoped_try_lock;
160 typedef mutex try_mutex;
166 #ifndef BOOST_PTHREAD_HAS_TIMEDLOCK
171 BOOST_THREAD_NO_COPYABLE(timed_mutex)
174 int const res=pthread_mutex_init(&m,NULL);
177 boost::throw_exception(thread_resource_error(res, "boost:: timed_mutex constructor failed in pthread_mutex_init"));
179 #ifndef BOOST_PTHREAD_HAS_TIMEDLOCK
180 int const res2=pthread_cond_init(&cond,NULL);
183 BOOST_VERIFY(!posix::pthread_mutex_destroy(&m));
184 //BOOST_VERIFY(!pthread_mutex_destroy(&m));
185 boost::throw_exception(thread_resource_error(res2, "boost:: timed_mutex constructor failed in pthread_cond_init"));
192 BOOST_VERIFY(!posix::pthread_mutex_destroy(&m));
193 #ifndef BOOST_PTHREAD_HAS_TIMEDLOCK
194 BOOST_VERIFY(!pthread_cond_destroy(&cond));
198 #if defined BOOST_THREAD_USES_DATETIME
199 template<typename TimeDuration>
200 bool timed_lock(TimeDuration const & relative_time)
202 return timed_lock(get_system_time()+relative_time);
204 bool timed_lock(boost::xtime const & absolute_time)
206 return timed_lock(system_time(absolute_time));
209 #ifdef BOOST_PTHREAD_HAS_TIMEDLOCK
212 int res = posix::pthread_mutex_lock(&m);
215 boost::throw_exception(lock_error(res,"boost: mutex lock failed in pthread_mutex_lock"));
221 int res = posix::pthread_mutex_unlock(&m);
224 boost::throw_exception(lock_error(res,"boost: mutex unlock failed in pthread_mutex_unlock"));
233 res = pthread_mutex_trylock(&m);
234 } while (res == EINTR);
245 bool do_try_lock_until(struct timespec const &timeout)
247 int const res=pthread_mutex_timedlock(&m,&timeout);
248 BOOST_ASSERT(!res || res==ETIMEDOUT);
256 boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
259 BOOST_VERIFY(!pthread_cond_wait(&cond,&m));
266 boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
268 BOOST_VERIFY(!pthread_cond_signal(&cond));
273 boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
283 bool do_try_lock_until(struct timespec const &timeout)
285 boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
288 int const cond_res=pthread_cond_timedwait(&cond,&m,&timeout);
289 if(cond_res==ETIMEDOUT)
293 BOOST_ASSERT(!cond_res);
301 #if defined BOOST_THREAD_USES_DATETIME
302 bool timed_lock(system_time const & abs_time)
304 struct timespec const ts=boost::detail::to_timespec(abs_time);
305 return do_try_lock_until(ts);
308 #ifdef BOOST_THREAD_USES_CHRONO
309 template <class Rep, class Period>
310 bool try_lock_for(const chrono::duration<Rep, Period>& rel_time)
312 return try_lock_until(chrono::steady_clock::now() + rel_time);
314 template <class Clock, class Duration>
315 bool try_lock_until(const chrono::time_point<Clock, Duration>& t)
317 using namespace chrono;
318 system_clock::time_point s_now = system_clock::now();
319 typename Clock::time_point c_now = Clock::now();
320 return try_lock_until(s_now + ceil<nanoseconds>(t - c_now));
322 template <class Duration>
323 bool try_lock_until(const chrono::time_point<chrono::system_clock, Duration>& t)
325 using namespace chrono;
326 typedef time_point<system_clock, nanoseconds> nano_sys_tmpt;
327 return try_lock_until(nano_sys_tmpt(ceil<nanoseconds>(t.time_since_epoch())));
329 bool try_lock_until(const chrono::time_point<chrono::system_clock, chrono::nanoseconds>& tp)
331 //using namespace chrono;
332 chrono::nanoseconds d = tp.time_since_epoch();
333 timespec ts = boost::detail::to_timespec(d);
334 return do_try_lock_until(ts);
338 #define BOOST_THREAD_DEFINES_TIMED_MUTEX_NATIVE_HANDLE
339 typedef pthread_mutex_t* native_handle_type;
340 native_handle_type native_handle()
345 #if defined BOOST_THREAD_PROVIDES_NESTED_LOCKS
346 typedef unique_lock<timed_mutex> scoped_timed_lock;
347 typedef detail::try_lock_wrapper<timed_mutex> scoped_try_lock;
348 typedef scoped_timed_lock scoped_lock;
354 #include <boost/config/abi_suffix.hpp>