1 #ifndef BOOST_THREAD_PTHREAD_RECURSIVE_MUTEX_HPP
2 #define BOOST_THREAD_PTHREAD_RECURSIVE_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)
10 #include <boost/throw_exception.hpp>
11 #include <boost/thread/exceptions.hpp>
12 #if defined BOOST_THREAD_PROVIDES_NESTED_LOCKS
13 #include <boost/thread/lock_types.hpp>
15 #include <boost/thread/thread_time.hpp>
16 #include <boost/assert.hpp>
20 #include <boost/date_time/posix_time/conversion.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
37 #if defined BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE \
38 || defined __ANDROID__
39 #define BOOST_THREAD_HAS_PTHREAD_MUTEXATTR_SETTYPE
42 #if defined BOOST_THREAD_HAS_PTHREAD_MUTEXATTR_SETTYPE && defined BOOST_PTHREAD_HAS_TIMEDLOCK
43 #define BOOST_USE_PTHREAD_RECURSIVE_TIMEDLOCK
46 #include <boost/config/abi_prefix.hpp>
54 #ifndef BOOST_THREAD_HAS_PTHREAD_MUTEXATTR_SETTYPE
61 BOOST_THREAD_NO_COPYABLE(recursive_mutex)
64 #ifdef BOOST_THREAD_HAS_PTHREAD_MUTEXATTR_SETTYPE
65 pthread_mutexattr_t attr;
67 int const init_attr_res=pthread_mutexattr_init(&attr);
70 boost::throw_exception(thread_resource_error(init_attr_res, "boost:: recursive_mutex constructor failed in pthread_mutexattr_init"));
72 int const set_attr_res=pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_RECURSIVE);
75 BOOST_VERIFY(!pthread_mutexattr_destroy(&attr));
76 boost::throw_exception(thread_resource_error(set_attr_res, "boost:: recursive_mutex constructor failed in pthread_mutexattr_settype"));
79 int const res=pthread_mutex_init(&m,&attr);
82 BOOST_VERIFY(!pthread_mutexattr_destroy(&attr));
83 boost::throw_exception(thread_resource_error(res, "boost:: recursive_mutex constructor failed in pthread_mutex_init"));
85 BOOST_VERIFY(!pthread_mutexattr_destroy(&attr));
87 int const res=pthread_mutex_init(&m,NULL);
90 boost::throw_exception(thread_resource_error(res, "boost:: recursive_mutex constructor failed in pthread_mutex_init"));
92 int const res2=pthread_cond_init(&cond,NULL);
95 BOOST_VERIFY(!pthread_mutex_destroy(&m));
96 boost::throw_exception(thread_resource_error(res2, "boost:: recursive_mutex constructor failed in pthread_cond_init"));
104 BOOST_VERIFY(!pthread_mutex_destroy(&m));
105 #ifndef BOOST_THREAD_HAS_PTHREAD_MUTEXATTR_SETTYPE
106 BOOST_VERIFY(!pthread_cond_destroy(&cond));
110 #ifdef BOOST_THREAD_HAS_PTHREAD_MUTEXATTR_SETTYPE
113 BOOST_VERIFY(!pthread_mutex_lock(&m));
118 BOOST_VERIFY(!pthread_mutex_unlock(&m));
121 bool try_lock() BOOST_NOEXCEPT
123 int const res=pthread_mutex_trylock(&m);
124 BOOST_ASSERT(!res || res==EBUSY);
127 #define BOOST_THREAD_DEFINES_RECURSIVE_MUTEX_NATIVE_HANDLE
128 typedef pthread_mutex_t* native_handle_type;
129 native_handle_type native_handle()
137 boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
138 if(is_locked && pthread_equal(owner,pthread_self()))
146 BOOST_VERIFY(!pthread_cond_wait(&cond,&m));
150 owner=pthread_self();
155 boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
160 BOOST_VERIFY(!pthread_cond_signal(&cond));
165 boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
166 if(is_locked && !pthread_equal(owner,pthread_self()))
172 owner=pthread_self();
178 #if defined BOOST_THREAD_PROVIDES_NESTED_LOCKS
179 typedef unique_lock<recursive_mutex> scoped_lock;
180 typedef detail::try_lock_wrapper<recursive_mutex> scoped_try_lock;
184 typedef recursive_mutex recursive_try_mutex;
186 class recursive_timed_mutex
190 #ifndef BOOST_USE_PTHREAD_RECURSIVE_TIMEDLOCK
197 BOOST_THREAD_NO_COPYABLE(recursive_timed_mutex)
198 recursive_timed_mutex()
200 #ifdef BOOST_USE_PTHREAD_RECURSIVE_TIMEDLOCK
201 pthread_mutexattr_t attr;
203 int const init_attr_res=pthread_mutexattr_init(&attr);
206 boost::throw_exception(thread_resource_error(init_attr_res, "boost:: recursive_timed_mutex constructor failed in pthread_mutexattr_init"));
208 int const set_attr_res=pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_RECURSIVE);
211 boost::throw_exception(thread_resource_error(set_attr_res, "boost:: recursive_timed_mutex constructor failed in pthread_mutexattr_settype"));
214 int const res=pthread_mutex_init(&m,&attr);
217 BOOST_VERIFY(!pthread_mutexattr_destroy(&attr));
218 boost::throw_exception(thread_resource_error(res, "boost:: recursive_timed_mutex constructor failed in pthread_mutex_init"));
220 BOOST_VERIFY(!pthread_mutexattr_destroy(&attr));
222 int const res=pthread_mutex_init(&m,NULL);
225 boost::throw_exception(thread_resource_error(res, "boost:: recursive_timed_mutex constructor failed in pthread_mutex_init"));
227 int const res2=pthread_cond_init(&cond,NULL);
230 BOOST_VERIFY(!pthread_mutex_destroy(&m));
231 boost::throw_exception(thread_resource_error(res2, "boost:: recursive_timed_mutex constructor failed in pthread_cond_init"));
237 ~recursive_timed_mutex()
239 BOOST_VERIFY(!pthread_mutex_destroy(&m));
240 #ifndef BOOST_USE_PTHREAD_RECURSIVE_TIMEDLOCK
241 BOOST_VERIFY(!pthread_cond_destroy(&cond));
245 #if defined BOOST_THREAD_USES_DATETIME
246 template<typename TimeDuration>
247 bool timed_lock(TimeDuration const & relative_time)
249 return timed_lock(get_system_time()+relative_time);
253 #ifdef BOOST_USE_PTHREAD_RECURSIVE_TIMEDLOCK
256 BOOST_VERIFY(!pthread_mutex_lock(&m));
261 BOOST_VERIFY(!pthread_mutex_unlock(&m));
266 int const res=pthread_mutex_trylock(&m);
267 BOOST_ASSERT(!res || res==EBUSY);
271 bool do_try_lock_until(struct timespec const &timeout)
273 int const res=pthread_mutex_timedlock(&m,&timeout);
274 BOOST_ASSERT(!res || res==ETIMEDOUT);
283 boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
284 if(is_locked && pthread_equal(owner,pthread_self()))
292 BOOST_VERIFY(!pthread_cond_wait(&cond,&m));
296 owner=pthread_self();
301 boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
306 BOOST_VERIFY(!pthread_cond_signal(&cond));
309 bool try_lock() BOOST_NOEXCEPT
311 boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
312 if(is_locked && !pthread_equal(owner,pthread_self()))
318 owner=pthread_self();
323 bool do_try_lock_until(struct timespec const &timeout)
325 boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
326 if(is_locked && pthread_equal(owner,pthread_self()))
333 int const cond_res=pthread_cond_timedwait(&cond,&m,&timeout);
334 if(cond_res==ETIMEDOUT)
338 BOOST_ASSERT(!cond_res);
342 owner=pthread_self();
349 #if defined BOOST_THREAD_USES_DATETIME
350 bool timed_lock(system_time const & abs_time)
352 struct timespec const ts=detail::to_timespec(abs_time);
353 return do_try_lock_until(ts);
356 #ifdef BOOST_THREAD_USES_CHRONO
357 template <class Rep, class Period>
358 bool try_lock_for(const chrono::duration<Rep, Period>& rel_time)
360 return try_lock_until(chrono::steady_clock::now() + rel_time);
362 template <class Clock, class Duration>
363 bool try_lock_until(const chrono::time_point<Clock, Duration>& t)
365 using namespace chrono;
366 system_clock::time_point s_now = system_clock::now();
367 typename Clock::time_point c_now = Clock::now();
368 return try_lock_until(s_now + ceil<nanoseconds>(t - c_now));
370 template <class Duration>
371 bool try_lock_until(const chrono::time_point<chrono::system_clock, Duration>& t)
373 using namespace chrono;
374 typedef time_point<system_clock, nanoseconds> nano_sys_tmpt;
375 return try_lock_until(nano_sys_tmpt(ceil<nanoseconds>(t.time_since_epoch())));
377 bool try_lock_until(const chrono::time_point<chrono::system_clock, chrono::nanoseconds>& tp)
379 //using namespace chrono;
380 chrono::nanoseconds d = tp.time_since_epoch();
381 timespec ts = boost::detail::to_timespec(d);
382 return do_try_lock_until(ts);
386 #define BOOST_THREAD_DEFINES_RECURSIVE_TIMED_MUTEX_NATIVE_HANDLE
387 typedef pthread_mutex_t* native_handle_type;
388 native_handle_type native_handle()
393 #if defined BOOST_THREAD_PROVIDES_NESTED_LOCKS
394 typedef unique_lock<recursive_timed_mutex> scoped_timed_lock;
395 typedef detail::try_lock_wrapper<recursive_timed_mutex> scoped_try_lock;
396 typedef scoped_timed_lock scoped_lock;
402 #include <boost/config/abi_suffix.hpp>