/src/contrib/boost/thread/pthread/recursive_mutex.hpp

http://pythonocc.googlecode.com/ · C++ Header · 267 lines · 234 code · 29 blank · 4 comment · 21 complexity · 0ff70cdd565f5ca258649d8f3ed1f93a MD5 · raw file

  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)
  7. #include <pthread.h>
  8. #include <boost/utility.hpp>
  9. #include <boost/throw_exception.hpp>
  10. #include <boost/thread/exceptions.hpp>
  11. #include <boost/thread/locks.hpp>
  12. #include <boost/thread/thread_time.hpp>
  13. #include <boost/assert.hpp>
  14. #ifndef _WIN32
  15. #include <unistd.h>
  16. #endif
  17. #include <boost/date_time/posix_time/conversion.hpp>
  18. #include <errno.h>
  19. #include "timespec.hpp"
  20. #include "pthread_mutex_scoped_lock.hpp"
  21. #ifdef _POSIX_TIMEOUTS
  22. #if _POSIX_TIMEOUTS >= 0
  23. #define BOOST_PTHREAD_HAS_TIMEDLOCK
  24. #endif
  25. #endif
  26. #include <boost/config/abi_prefix.hpp>
  27. namespace boost
  28. {
  29. class recursive_mutex:
  30. boost::noncopyable
  31. {
  32. private:
  33. pthread_mutex_t m;
  34. public:
  35. recursive_mutex()
  36. {
  37. pthread_mutexattr_t attr;
  38. int const init_attr_res=pthread_mutexattr_init(&attr);
  39. if(init_attr_res)
  40. {
  41. boost::throw_exception(thread_resource_error());
  42. }
  43. int const set_attr_res=pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_RECURSIVE);
  44. if(set_attr_res)
  45. {
  46. boost::throw_exception(thread_resource_error());
  47. }
  48. int const res=pthread_mutex_init(&m,&attr);
  49. if(res)
  50. {
  51. boost::throw_exception(thread_resource_error());
  52. }
  53. BOOST_VERIFY(!pthread_mutexattr_destroy(&attr));
  54. }
  55. ~recursive_mutex()
  56. {
  57. BOOST_VERIFY(!pthread_mutex_destroy(&m));
  58. }
  59. void lock()
  60. {
  61. BOOST_VERIFY(!pthread_mutex_lock(&m));
  62. }
  63. void unlock()
  64. {
  65. BOOST_VERIFY(!pthread_mutex_unlock(&m));
  66. }
  67. bool try_lock()
  68. {
  69. int const res=pthread_mutex_trylock(&m);
  70. BOOST_ASSERT(!res || res==EBUSY);
  71. return !res;
  72. }
  73. typedef pthread_mutex_t* native_handle_type;
  74. native_handle_type native_handle()
  75. {
  76. return &m;
  77. }
  78. typedef unique_lock<recursive_mutex> scoped_lock;
  79. typedef detail::try_lock_wrapper<recursive_mutex> scoped_try_lock;
  80. };
  81. typedef recursive_mutex recursive_try_mutex;
  82. class recursive_timed_mutex:
  83. boost::noncopyable
  84. {
  85. private:
  86. pthread_mutex_t m;
  87. #ifndef BOOST_PTHREAD_HAS_TIMEDLOCK
  88. pthread_cond_t cond;
  89. bool is_locked;
  90. pthread_t owner;
  91. unsigned count;
  92. #endif
  93. public:
  94. recursive_timed_mutex()
  95. {
  96. #ifdef BOOST_PTHREAD_HAS_TIMEDLOCK
  97. pthread_mutexattr_t attr;
  98. int const init_attr_res=pthread_mutexattr_init(&attr);
  99. if(init_attr_res)
  100. {
  101. boost::throw_exception(thread_resource_error());
  102. }
  103. int const set_attr_res=pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_RECURSIVE);
  104. if(set_attr_res)
  105. {
  106. boost::throw_exception(thread_resource_error());
  107. }
  108. int const res=pthread_mutex_init(&m,&attr);
  109. if(res)
  110. {
  111. BOOST_VERIFY(!pthread_mutexattr_destroy(&attr));
  112. boost::throw_exception(thread_resource_error());
  113. }
  114. BOOST_VERIFY(!pthread_mutexattr_destroy(&attr));
  115. #else
  116. int const res=pthread_mutex_init(&m,NULL);
  117. if(res)
  118. {
  119. boost::throw_exception(thread_resource_error());
  120. }
  121. int const res2=pthread_cond_init(&cond,NULL);
  122. if(res2)
  123. {
  124. BOOST_VERIFY(!pthread_mutex_destroy(&m));
  125. boost::throw_exception(thread_resource_error());
  126. }
  127. is_locked=false;
  128. count=0;
  129. #endif
  130. }
  131. ~recursive_timed_mutex()
  132. {
  133. BOOST_VERIFY(!pthread_mutex_destroy(&m));
  134. #ifndef BOOST_PTHREAD_HAS_TIMEDLOCK
  135. BOOST_VERIFY(!pthread_cond_destroy(&cond));
  136. #endif
  137. }
  138. template<typename TimeDuration>
  139. bool timed_lock(TimeDuration const & relative_time)
  140. {
  141. return timed_lock(get_system_time()+relative_time);
  142. }
  143. #ifdef BOOST_PTHREAD_HAS_TIMEDLOCK
  144. void lock()
  145. {
  146. BOOST_VERIFY(!pthread_mutex_lock(&m));
  147. }
  148. void unlock()
  149. {
  150. BOOST_VERIFY(!pthread_mutex_unlock(&m));
  151. }
  152. bool try_lock()
  153. {
  154. int const res=pthread_mutex_trylock(&m);
  155. BOOST_ASSERT(!res || res==EBUSY);
  156. return !res;
  157. }
  158. bool timed_lock(system_time const & abs_time)
  159. {
  160. struct timespec const timeout=detail::get_timespec(abs_time);
  161. int const res=pthread_mutex_timedlock(&m,&timeout);
  162. BOOST_ASSERT(!res || res==ETIMEDOUT);
  163. return !res;
  164. }
  165. typedef pthread_mutex_t* native_handle_type;
  166. native_handle_type native_handle()
  167. {
  168. return &m;
  169. }
  170. #else
  171. void lock()
  172. {
  173. boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
  174. if(is_locked && pthread_equal(owner,pthread_self()))
  175. {
  176. ++count;
  177. return;
  178. }
  179. while(is_locked)
  180. {
  181. BOOST_VERIFY(!pthread_cond_wait(&cond,&m));
  182. }
  183. is_locked=true;
  184. ++count;
  185. owner=pthread_self();
  186. }
  187. void unlock()
  188. {
  189. boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
  190. if(!--count)
  191. {
  192. is_locked=false;
  193. }
  194. BOOST_VERIFY(!pthread_cond_signal(&cond));
  195. }
  196. bool try_lock()
  197. {
  198. boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
  199. if(is_locked && !pthread_equal(owner,pthread_self()))
  200. {
  201. return false;
  202. }
  203. is_locked=true;
  204. ++count;
  205. owner=pthread_self();
  206. return true;
  207. }
  208. bool timed_lock(system_time const & abs_time)
  209. {
  210. struct timespec const timeout=detail::get_timespec(abs_time);
  211. boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
  212. if(is_locked && pthread_equal(owner,pthread_self()))
  213. {
  214. ++count;
  215. return true;
  216. }
  217. while(is_locked)
  218. {
  219. int const cond_res=pthread_cond_timedwait(&cond,&m,&timeout);
  220. if(cond_res==ETIMEDOUT)
  221. {
  222. return false;
  223. }
  224. BOOST_ASSERT(!cond_res);
  225. }
  226. is_locked=true;
  227. ++count;
  228. owner=pthread_self();
  229. return true;
  230. }
  231. #endif
  232. typedef unique_lock<recursive_timed_mutex> scoped_timed_lock;
  233. typedef detail::try_lock_wrapper<recursive_timed_mutex> scoped_try_lock;
  234. typedef scoped_timed_lock scoped_lock;
  235. };
  236. }
  237. #include <boost/config/abi_suffix.hpp>
  238. #endif