annotate DEPENDENCIES/generic/include/boost/thread/pthread/recursive_mutex.hpp @ 133:4acb5d8d80b6 tip

Don't fail environmental check if README.md exists (but .txt and no-suffix don't)
author Chris Cannam
date Tue, 30 Jul 2019 12:25:44 +0100
parents c530137014c0
children
rev   line source
Chris@16 1 #ifndef BOOST_THREAD_PTHREAD_RECURSIVE_MUTEX_HPP
Chris@16 2 #define BOOST_THREAD_PTHREAD_RECURSIVE_MUTEX_HPP
Chris@16 3 // (C) Copyright 2007-8 Anthony Williams
Chris@16 4 // (C) Copyright 2011-2012 Vicente J. Botet Escriba
Chris@16 5 // Distributed under the Boost Software License, Version 1.0. (See
Chris@16 6 // accompanying file LICENSE_1_0.txt or copy at
Chris@16 7 // http://www.boost.org/LICENSE_1_0.txt)
Chris@16 8
Chris@16 9 #include <pthread.h>
Chris@16 10 #include <boost/throw_exception.hpp>
Chris@16 11 #include <boost/thread/exceptions.hpp>
Chris@16 12 #if defined BOOST_THREAD_PROVIDES_NESTED_LOCKS
Chris@16 13 #include <boost/thread/lock_types.hpp>
Chris@16 14 #endif
Chris@16 15 #include <boost/thread/thread_time.hpp>
Chris@16 16 #include <boost/assert.hpp>
Chris@16 17 #ifndef _WIN32
Chris@16 18 #include <unistd.h>
Chris@16 19 #endif
Chris@16 20 #include <boost/date_time/posix_time/conversion.hpp>
Chris@16 21 #include <errno.h>
Chris@16 22 #include <boost/thread/pthread/timespec.hpp>
Chris@16 23 #include <boost/thread/pthread/pthread_mutex_scoped_lock.hpp>
Chris@16 24 #ifdef BOOST_THREAD_USES_CHRONO
Chris@16 25 #include <boost/chrono/system_clocks.hpp>
Chris@16 26 #include <boost/chrono/ceil.hpp>
Chris@16 27 #endif
Chris@16 28 #include <boost/thread/detail/delete.hpp>
Chris@16 29
Chris@101 30 #if (defined _POSIX_TIMEOUTS && (_POSIX_TIMEOUTS-0)>=200112L) \
Chris@101 31 || (defined __ANDROID__ && defined __ANDROID_API__ && __ANDROID_API__ >= 21)
Chris@16 32 #ifndef BOOST_PTHREAD_HAS_TIMEDLOCK
Chris@16 33 #define BOOST_PTHREAD_HAS_TIMEDLOCK
Chris@16 34 #endif
Chris@16 35 #endif
Chris@101 36
Chris@101 37 #if defined BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE \
Chris@101 38 || defined __ANDROID__
Chris@101 39 #define BOOST_THREAD_HAS_PTHREAD_MUTEXATTR_SETTYPE
Chris@16 40 #endif
Chris@16 41
Chris@101 42 #if defined BOOST_THREAD_HAS_PTHREAD_MUTEXATTR_SETTYPE && defined BOOST_PTHREAD_HAS_TIMEDLOCK
Chris@16 43 #define BOOST_USE_PTHREAD_RECURSIVE_TIMEDLOCK
Chris@16 44 #endif
Chris@16 45
Chris@16 46 #include <boost/config/abi_prefix.hpp>
Chris@16 47
Chris@16 48 namespace boost
Chris@16 49 {
Chris@16 50 class recursive_mutex
Chris@16 51 {
Chris@16 52 private:
Chris@16 53 pthread_mutex_t m;
Chris@101 54 #ifndef BOOST_THREAD_HAS_PTHREAD_MUTEXATTR_SETTYPE
Chris@16 55 pthread_cond_t cond;
Chris@16 56 bool is_locked;
Chris@16 57 pthread_t owner;
Chris@16 58 unsigned count;
Chris@16 59 #endif
Chris@16 60 public:
Chris@16 61 BOOST_THREAD_NO_COPYABLE(recursive_mutex)
Chris@16 62 recursive_mutex()
Chris@16 63 {
Chris@101 64 #ifdef BOOST_THREAD_HAS_PTHREAD_MUTEXATTR_SETTYPE
Chris@16 65 pthread_mutexattr_t attr;
Chris@16 66
Chris@16 67 int const init_attr_res=pthread_mutexattr_init(&attr);
Chris@16 68 if(init_attr_res)
Chris@16 69 {
Chris@16 70 boost::throw_exception(thread_resource_error(init_attr_res, "boost:: recursive_mutex constructor failed in pthread_mutexattr_init"));
Chris@16 71 }
Chris@16 72 int const set_attr_res=pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_RECURSIVE);
Chris@16 73 if(set_attr_res)
Chris@16 74 {
Chris@16 75 BOOST_VERIFY(!pthread_mutexattr_destroy(&attr));
Chris@16 76 boost::throw_exception(thread_resource_error(set_attr_res, "boost:: recursive_mutex constructor failed in pthread_mutexattr_settype"));
Chris@16 77 }
Chris@16 78
Chris@16 79 int const res=pthread_mutex_init(&m,&attr);
Chris@16 80 if(res)
Chris@16 81 {
Chris@16 82 BOOST_VERIFY(!pthread_mutexattr_destroy(&attr));
Chris@16 83 boost::throw_exception(thread_resource_error(res, "boost:: recursive_mutex constructor failed in pthread_mutex_init"));
Chris@16 84 }
Chris@16 85 BOOST_VERIFY(!pthread_mutexattr_destroy(&attr));
Chris@16 86 #else
Chris@16 87 int const res=pthread_mutex_init(&m,NULL);
Chris@16 88 if(res)
Chris@16 89 {
Chris@16 90 boost::throw_exception(thread_resource_error(res, "boost:: recursive_mutex constructor failed in pthread_mutex_init"));
Chris@16 91 }
Chris@16 92 int const res2=pthread_cond_init(&cond,NULL);
Chris@16 93 if(res2)
Chris@16 94 {
Chris@16 95 BOOST_VERIFY(!pthread_mutex_destroy(&m));
Chris@16 96 boost::throw_exception(thread_resource_error(res2, "boost:: recursive_mutex constructor failed in pthread_cond_init"));
Chris@16 97 }
Chris@16 98 is_locked=false;
Chris@16 99 count=0;
Chris@16 100 #endif
Chris@16 101 }
Chris@16 102 ~recursive_mutex()
Chris@16 103 {
Chris@16 104 BOOST_VERIFY(!pthread_mutex_destroy(&m));
Chris@101 105 #ifndef BOOST_THREAD_HAS_PTHREAD_MUTEXATTR_SETTYPE
Chris@16 106 BOOST_VERIFY(!pthread_cond_destroy(&cond));
Chris@16 107 #endif
Chris@16 108 }
Chris@16 109
Chris@101 110 #ifdef BOOST_THREAD_HAS_PTHREAD_MUTEXATTR_SETTYPE
Chris@16 111 void lock()
Chris@16 112 {
Chris@16 113 BOOST_VERIFY(!pthread_mutex_lock(&m));
Chris@16 114 }
Chris@16 115
Chris@16 116 void unlock()
Chris@16 117 {
Chris@16 118 BOOST_VERIFY(!pthread_mutex_unlock(&m));
Chris@16 119 }
Chris@16 120
Chris@16 121 bool try_lock() BOOST_NOEXCEPT
Chris@16 122 {
Chris@16 123 int const res=pthread_mutex_trylock(&m);
Chris@16 124 BOOST_ASSERT(!res || res==EBUSY);
Chris@16 125 return !res;
Chris@16 126 }
Chris@16 127 #define BOOST_THREAD_DEFINES_RECURSIVE_MUTEX_NATIVE_HANDLE
Chris@16 128 typedef pthread_mutex_t* native_handle_type;
Chris@16 129 native_handle_type native_handle()
Chris@16 130 {
Chris@16 131 return &m;
Chris@16 132 }
Chris@16 133
Chris@16 134 #else
Chris@16 135 void lock()
Chris@16 136 {
Chris@16 137 boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
Chris@16 138 if(is_locked && pthread_equal(owner,pthread_self()))
Chris@16 139 {
Chris@16 140 ++count;
Chris@16 141 return;
Chris@16 142 }
Chris@16 143
Chris@16 144 while(is_locked)
Chris@16 145 {
Chris@16 146 BOOST_VERIFY(!pthread_cond_wait(&cond,&m));
Chris@16 147 }
Chris@16 148 is_locked=true;
Chris@16 149 ++count;
Chris@16 150 owner=pthread_self();
Chris@16 151 }
Chris@16 152
Chris@16 153 void unlock()
Chris@16 154 {
Chris@16 155 boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
Chris@16 156 if(!--count)
Chris@16 157 {
Chris@16 158 is_locked=false;
Chris@16 159 }
Chris@16 160 BOOST_VERIFY(!pthread_cond_signal(&cond));
Chris@16 161 }
Chris@16 162
Chris@16 163 bool try_lock()
Chris@16 164 {
Chris@16 165 boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
Chris@16 166 if(is_locked && !pthread_equal(owner,pthread_self()))
Chris@16 167 {
Chris@16 168 return false;
Chris@16 169 }
Chris@16 170 is_locked=true;
Chris@16 171 ++count;
Chris@16 172 owner=pthread_self();
Chris@16 173 return true;
Chris@16 174 }
Chris@16 175
Chris@16 176 #endif
Chris@16 177
Chris@16 178 #if defined BOOST_THREAD_PROVIDES_NESTED_LOCKS
Chris@16 179 typedef unique_lock<recursive_mutex> scoped_lock;
Chris@16 180 typedef detail::try_lock_wrapper<recursive_mutex> scoped_try_lock;
Chris@16 181 #endif
Chris@16 182 };
Chris@16 183
Chris@16 184 typedef recursive_mutex recursive_try_mutex;
Chris@16 185
Chris@16 186 class recursive_timed_mutex
Chris@16 187 {
Chris@16 188 private:
Chris@16 189 pthread_mutex_t m;
Chris@16 190 #ifndef BOOST_USE_PTHREAD_RECURSIVE_TIMEDLOCK
Chris@16 191 pthread_cond_t cond;
Chris@16 192 bool is_locked;
Chris@16 193 pthread_t owner;
Chris@16 194 unsigned count;
Chris@16 195 #endif
Chris@16 196 public:
Chris@16 197 BOOST_THREAD_NO_COPYABLE(recursive_timed_mutex)
Chris@16 198 recursive_timed_mutex()
Chris@16 199 {
Chris@16 200 #ifdef BOOST_USE_PTHREAD_RECURSIVE_TIMEDLOCK
Chris@16 201 pthread_mutexattr_t attr;
Chris@16 202
Chris@16 203 int const init_attr_res=pthread_mutexattr_init(&attr);
Chris@16 204 if(init_attr_res)
Chris@16 205 {
Chris@16 206 boost::throw_exception(thread_resource_error(init_attr_res, "boost:: recursive_timed_mutex constructor failed in pthread_mutexattr_init"));
Chris@16 207 }
Chris@16 208 int const set_attr_res=pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_RECURSIVE);
Chris@16 209 if(set_attr_res)
Chris@16 210 {
Chris@16 211 boost::throw_exception(thread_resource_error(set_attr_res, "boost:: recursive_timed_mutex constructor failed in pthread_mutexattr_settype"));
Chris@16 212 }
Chris@16 213
Chris@16 214 int const res=pthread_mutex_init(&m,&attr);
Chris@16 215 if(res)
Chris@16 216 {
Chris@16 217 BOOST_VERIFY(!pthread_mutexattr_destroy(&attr));
Chris@16 218 boost::throw_exception(thread_resource_error(res, "boost:: recursive_timed_mutex constructor failed in pthread_mutex_init"));
Chris@16 219 }
Chris@16 220 BOOST_VERIFY(!pthread_mutexattr_destroy(&attr));
Chris@16 221 #else
Chris@16 222 int const res=pthread_mutex_init(&m,NULL);
Chris@16 223 if(res)
Chris@16 224 {
Chris@16 225 boost::throw_exception(thread_resource_error(res, "boost:: recursive_timed_mutex constructor failed in pthread_mutex_init"));
Chris@16 226 }
Chris@16 227 int const res2=pthread_cond_init(&cond,NULL);
Chris@16 228 if(res2)
Chris@16 229 {
Chris@16 230 BOOST_VERIFY(!pthread_mutex_destroy(&m));
Chris@16 231 boost::throw_exception(thread_resource_error(res2, "boost:: recursive_timed_mutex constructor failed in pthread_cond_init"));
Chris@16 232 }
Chris@16 233 is_locked=false;
Chris@16 234 count=0;
Chris@16 235 #endif
Chris@16 236 }
Chris@16 237 ~recursive_timed_mutex()
Chris@16 238 {
Chris@16 239 BOOST_VERIFY(!pthread_mutex_destroy(&m));
Chris@16 240 #ifndef BOOST_USE_PTHREAD_RECURSIVE_TIMEDLOCK
Chris@16 241 BOOST_VERIFY(!pthread_cond_destroy(&cond));
Chris@16 242 #endif
Chris@16 243 }
Chris@16 244
Chris@16 245 #if defined BOOST_THREAD_USES_DATETIME
Chris@16 246 template<typename TimeDuration>
Chris@16 247 bool timed_lock(TimeDuration const & relative_time)
Chris@16 248 {
Chris@16 249 return timed_lock(get_system_time()+relative_time);
Chris@16 250 }
Chris@16 251 #endif
Chris@16 252
Chris@16 253 #ifdef BOOST_USE_PTHREAD_RECURSIVE_TIMEDLOCK
Chris@16 254 void lock()
Chris@16 255 {
Chris@16 256 BOOST_VERIFY(!pthread_mutex_lock(&m));
Chris@16 257 }
Chris@16 258
Chris@16 259 void unlock()
Chris@16 260 {
Chris@16 261 BOOST_VERIFY(!pthread_mutex_unlock(&m));
Chris@16 262 }
Chris@16 263
Chris@16 264 bool try_lock()
Chris@16 265 {
Chris@16 266 int const res=pthread_mutex_trylock(&m);
Chris@16 267 BOOST_ASSERT(!res || res==EBUSY);
Chris@16 268 return !res;
Chris@16 269 }
Chris@16 270 private:
Chris@16 271 bool do_try_lock_until(struct timespec const &timeout)
Chris@16 272 {
Chris@16 273 int const res=pthread_mutex_timedlock(&m,&timeout);
Chris@16 274 BOOST_ASSERT(!res || res==ETIMEDOUT);
Chris@16 275 return !res;
Chris@16 276 }
Chris@16 277
Chris@16 278 public:
Chris@16 279
Chris@16 280 #else
Chris@16 281 void lock()
Chris@16 282 {
Chris@16 283 boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
Chris@16 284 if(is_locked && pthread_equal(owner,pthread_self()))
Chris@16 285 {
Chris@16 286 ++count;
Chris@16 287 return;
Chris@16 288 }
Chris@16 289
Chris@16 290 while(is_locked)
Chris@16 291 {
Chris@16 292 BOOST_VERIFY(!pthread_cond_wait(&cond,&m));
Chris@16 293 }
Chris@16 294 is_locked=true;
Chris@16 295 ++count;
Chris@16 296 owner=pthread_self();
Chris@16 297 }
Chris@16 298
Chris@16 299 void unlock()
Chris@16 300 {
Chris@16 301 boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
Chris@16 302 if(!--count)
Chris@16 303 {
Chris@16 304 is_locked=false;
Chris@16 305 }
Chris@16 306 BOOST_VERIFY(!pthread_cond_signal(&cond));
Chris@16 307 }
Chris@16 308
Chris@16 309 bool try_lock() BOOST_NOEXCEPT
Chris@16 310 {
Chris@16 311 boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
Chris@16 312 if(is_locked && !pthread_equal(owner,pthread_self()))
Chris@16 313 {
Chris@16 314 return false;
Chris@16 315 }
Chris@16 316 is_locked=true;
Chris@16 317 ++count;
Chris@16 318 owner=pthread_self();
Chris@16 319 return true;
Chris@16 320 }
Chris@16 321
Chris@16 322 private:
Chris@16 323 bool do_try_lock_until(struct timespec const &timeout)
Chris@16 324 {
Chris@16 325 boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
Chris@16 326 if(is_locked && pthread_equal(owner,pthread_self()))
Chris@16 327 {
Chris@16 328 ++count;
Chris@16 329 return true;
Chris@16 330 }
Chris@16 331 while(is_locked)
Chris@16 332 {
Chris@16 333 int const cond_res=pthread_cond_timedwait(&cond,&m,&timeout);
Chris@16 334 if(cond_res==ETIMEDOUT)
Chris@16 335 {
Chris@16 336 return false;
Chris@16 337 }
Chris@16 338 BOOST_ASSERT(!cond_res);
Chris@16 339 }
Chris@16 340 is_locked=true;
Chris@16 341 ++count;
Chris@16 342 owner=pthread_self();
Chris@16 343 return true;
Chris@16 344 }
Chris@16 345 public:
Chris@16 346
Chris@16 347 #endif
Chris@16 348
Chris@16 349 #if defined BOOST_THREAD_USES_DATETIME
Chris@16 350 bool timed_lock(system_time const & abs_time)
Chris@16 351 {
Chris@16 352 struct timespec const ts=detail::to_timespec(abs_time);
Chris@16 353 return do_try_lock_until(ts);
Chris@16 354 }
Chris@16 355 #endif
Chris@16 356 #ifdef BOOST_THREAD_USES_CHRONO
Chris@16 357 template <class Rep, class Period>
Chris@16 358 bool try_lock_for(const chrono::duration<Rep, Period>& rel_time)
Chris@16 359 {
Chris@16 360 return try_lock_until(chrono::steady_clock::now() + rel_time);
Chris@16 361 }
Chris@16 362 template <class Clock, class Duration>
Chris@16 363 bool try_lock_until(const chrono::time_point<Clock, Duration>& t)
Chris@16 364 {
Chris@16 365 using namespace chrono;
Chris@16 366 system_clock::time_point s_now = system_clock::now();
Chris@16 367 typename Clock::time_point c_now = Clock::now();
Chris@16 368 return try_lock_until(s_now + ceil<nanoseconds>(t - c_now));
Chris@16 369 }
Chris@16 370 template <class Duration>
Chris@16 371 bool try_lock_until(const chrono::time_point<chrono::system_clock, Duration>& t)
Chris@16 372 {
Chris@16 373 using namespace chrono;
Chris@16 374 typedef time_point<system_clock, nanoseconds> nano_sys_tmpt;
Chris@16 375 return try_lock_until(nano_sys_tmpt(ceil<nanoseconds>(t.time_since_epoch())));
Chris@16 376 }
Chris@16 377 bool try_lock_until(const chrono::time_point<chrono::system_clock, chrono::nanoseconds>& tp)
Chris@16 378 {
Chris@16 379 //using namespace chrono;
Chris@16 380 chrono::nanoseconds d = tp.time_since_epoch();
Chris@16 381 timespec ts = boost::detail::to_timespec(d);
Chris@16 382 return do_try_lock_until(ts);
Chris@16 383 }
Chris@16 384 #endif
Chris@16 385
Chris@16 386 #define BOOST_THREAD_DEFINES_RECURSIVE_TIMED_MUTEX_NATIVE_HANDLE
Chris@16 387 typedef pthread_mutex_t* native_handle_type;
Chris@16 388 native_handle_type native_handle()
Chris@16 389 {
Chris@16 390 return &m;
Chris@16 391 }
Chris@16 392
Chris@16 393 #if defined BOOST_THREAD_PROVIDES_NESTED_LOCKS
Chris@16 394 typedef unique_lock<recursive_timed_mutex> scoped_timed_lock;
Chris@16 395 typedef detail::try_lock_wrapper<recursive_timed_mutex> scoped_try_lock;
Chris@16 396 typedef scoped_timed_lock scoped_lock;
Chris@16 397 #endif
Chris@16 398 };
Chris@16 399
Chris@16 400 }
Chris@16 401
Chris@16 402 #include <boost/config/abi_suffix.hpp>
Chris@16 403
Chris@16 404 #endif