1 #ifndef BOOST_THREAD_PTHREAD_RECURSIVE_MUTEX_HPP
2 #define BOOST_THREAD_PTHREAD_RECURSIVE_MUTEX_HPP
3 // (C) Copyright 2007-8 Anthony Williams
4 // Distributed under the Boost Software License, Version 1.0. (See
5 // accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt)
9 #include <boost/utility.hpp>
10 #include <boost/throw_exception.hpp>
11 #include <boost/thread/exceptions.hpp>
12 #include <boost/thread/locks.hpp>
13 #include <boost/thread/thread_time.hpp>
14 #include <boost/assert.hpp>
18 #include <boost/date_time/posix_time/conversion.hpp>
20 #include <boost/thread/pthread/timespec.hpp>
21 #include <boost/thread/pthread/pthread_mutex_scoped_lock.hpp>
23 #ifdef _POSIX_TIMEOUTS
24 #if _POSIX_TIMEOUTS >= 0
25 #define BOOST_PTHREAD_HAS_TIMEDLOCK
29 #if defined(BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE) && defined(BOOST_PTHREAD_HAS_TIMEDLOCK)
30 #define BOOST_USE_PTHREAD_RECURSIVE_TIMEDLOCK
33 #include <boost/config/abi_prefix.hpp>
40 recursive_mutex(recursive_mutex const&);
41 recursive_mutex& operator=(recursive_mutex const&);
43 #ifndef BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE
52 #ifdef BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE
53 pthread_mutexattr_t attr;
55 int const init_attr_res=pthread_mutexattr_init(&attr);
58 boost::throw_exception(thread_resource_error());
60 int const set_attr_res=pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_RECURSIVE);
63 BOOST_VERIFY(!pthread_mutexattr_destroy(&attr));
64 boost::throw_exception(thread_resource_error());
67 int const res=pthread_mutex_init(&m,&attr);
70 BOOST_VERIFY(!pthread_mutexattr_destroy(&attr));
71 boost::throw_exception(thread_resource_error());
73 BOOST_VERIFY(!pthread_mutexattr_destroy(&attr));
75 int const res=pthread_mutex_init(&m,NULL);
78 boost::throw_exception(thread_resource_error());
80 int const res2=pthread_cond_init(&cond,NULL);
83 BOOST_VERIFY(!pthread_mutex_destroy(&m));
84 boost::throw_exception(thread_resource_error());
92 BOOST_VERIFY(!pthread_mutex_destroy(&m));
93 #ifndef BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE
94 BOOST_VERIFY(!pthread_cond_destroy(&cond));
98 #ifdef BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE
101 BOOST_VERIFY(!pthread_mutex_lock(&m));
106 BOOST_VERIFY(!pthread_mutex_unlock(&m));
111 int const res=pthread_mutex_trylock(&m);
112 BOOST_ASSERT(!res || res==EBUSY);
115 typedef pthread_mutex_t* native_handle_type;
116 native_handle_type native_handle()
124 boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
125 if(is_locked && pthread_equal(owner,pthread_self()))
133 BOOST_VERIFY(!pthread_cond_wait(&cond,&m));
137 owner=pthread_self();
142 boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
147 BOOST_VERIFY(!pthread_cond_signal(&cond));
152 boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
153 if(is_locked && !pthread_equal(owner,pthread_self()))
159 owner=pthread_self();
165 typedef unique_lock<recursive_mutex> scoped_lock;
166 typedef detail::try_lock_wrapper<recursive_mutex> scoped_try_lock;
169 typedef recursive_mutex recursive_try_mutex;
171 class recursive_timed_mutex
174 recursive_timed_mutex(recursive_timed_mutex const&);
175 recursive_timed_mutex& operator=(recursive_timed_mutex const&);
178 #ifndef BOOST_USE_PTHREAD_RECURSIVE_TIMEDLOCK
185 recursive_timed_mutex()
187 #ifdef BOOST_USE_PTHREAD_RECURSIVE_TIMEDLOCK
188 pthread_mutexattr_t attr;
190 int const init_attr_res=pthread_mutexattr_init(&attr);
193 boost::throw_exception(thread_resource_error());
195 int const set_attr_res=pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_RECURSIVE);
198 boost::throw_exception(thread_resource_error());
201 int const res=pthread_mutex_init(&m,&attr);
204 BOOST_VERIFY(!pthread_mutexattr_destroy(&attr));
205 boost::throw_exception(thread_resource_error());
207 BOOST_VERIFY(!pthread_mutexattr_destroy(&attr));
209 int const res=pthread_mutex_init(&m,NULL);
212 boost::throw_exception(thread_resource_error());
214 int const res2=pthread_cond_init(&cond,NULL);
217 BOOST_VERIFY(!pthread_mutex_destroy(&m));
218 boost::throw_exception(thread_resource_error());
224 ~recursive_timed_mutex()
226 BOOST_VERIFY(!pthread_mutex_destroy(&m));
227 #ifndef BOOST_USE_PTHREAD_RECURSIVE_TIMEDLOCK
228 BOOST_VERIFY(!pthread_cond_destroy(&cond));
232 template<typename TimeDuration>
233 bool timed_lock(TimeDuration const & relative_time)
235 return timed_lock(get_system_time()+relative_time);
238 #ifdef BOOST_USE_PTHREAD_RECURSIVE_TIMEDLOCK
241 BOOST_VERIFY(!pthread_mutex_lock(&m));
246 BOOST_VERIFY(!pthread_mutex_unlock(&m));
251 int const res=pthread_mutex_trylock(&m);
252 BOOST_ASSERT(!res || res==EBUSY);
255 bool timed_lock(system_time const & abs_time)
257 struct timespec const timeout=detail::get_timespec(abs_time);
258 int const res=pthread_mutex_timedlock(&m,&timeout);
259 BOOST_ASSERT(!res || res==ETIMEDOUT);
263 typedef pthread_mutex_t* native_handle_type;
264 native_handle_type native_handle()
272 boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
273 if(is_locked && pthread_equal(owner,pthread_self()))
281 BOOST_VERIFY(!pthread_cond_wait(&cond,&m));
285 owner=pthread_self();
290 boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
295 BOOST_VERIFY(!pthread_cond_signal(&cond));
300 boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
301 if(is_locked && !pthread_equal(owner,pthread_self()))
307 owner=pthread_self();
311 bool timed_lock(system_time const & abs_time)
313 struct timespec const timeout=detail::get_timespec(abs_time);
314 boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
315 if(is_locked && pthread_equal(owner,pthread_self()))
322 int const cond_res=pthread_cond_timedwait(&cond,&m,&timeout);
323 if(cond_res==ETIMEDOUT)
327 BOOST_ASSERT(!cond_res);
331 owner=pthread_self();
336 typedef unique_lock<recursive_timed_mutex> scoped_timed_lock;
337 typedef detail::try_lock_wrapper<recursive_timed_mutex> scoped_try_lock;
338 typedef scoped_timed_lock scoped_lock;
343 #include <boost/config/abi_suffix.hpp>