annotate DEPENDENCIES/generic/include/boost/thread/v2/shared_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 2665513ce2d3
children
rev   line source
Chris@16 1 #ifndef BOOST_THREAD_V2_SHARED_MUTEX_HPP
Chris@16 2 #define BOOST_THREAD_V2_SHARED_MUTEX_HPP
Chris@16 3
Chris@16 4 // shared_mutex.hpp
Chris@16 5 //
Chris@16 6 // Copyright Howard Hinnant 2007-2010.
Chris@16 7 // Copyright Vicente J. Botet Escriba 2012.
Chris@16 8 //
Chris@16 9 // Distributed under the Boost Software License, Version 1.0. (See
Chris@16 10 // accompanying file LICENSE_1_0.txt or copy at
Chris@16 11 // http://www.boost.org/LICENSE_1_0.txt)
Chris@16 12
Chris@16 13 /*
Chris@16 14 <shared_mutex> synopsis
Chris@16 15
Chris@16 16 namespace boost
Chris@16 17 {
Chris@16 18 namespace thread_v2
Chris@16 19 {
Chris@16 20
Chris@16 21 class shared_mutex
Chris@16 22 {
Chris@16 23 public:
Chris@16 24
Chris@16 25 shared_mutex();
Chris@16 26 ~shared_mutex();
Chris@16 27
Chris@16 28 shared_mutex(const shared_mutex&) = delete;
Chris@16 29 shared_mutex& operator=(const shared_mutex&) = delete;
Chris@16 30
Chris@16 31 // Exclusive ownership
Chris@16 32
Chris@16 33 void lock();
Chris@16 34 bool try_lock();
Chris@16 35 template <class Rep, class Period>
Chris@16 36 bool try_lock_for(const boost::chrono::duration<Rep, Period>& rel_time);
Chris@16 37 template <class Clock, class Duration>
Chris@16 38 bool
Chris@16 39 try_lock_until(
Chris@16 40 const boost::chrono::time_point<Clock, Duration>& abs_time);
Chris@16 41 void unlock();
Chris@16 42
Chris@16 43 // Shared ownership
Chris@16 44
Chris@16 45 void lock_shared();
Chris@16 46 bool try_lock_shared();
Chris@16 47 template <class Rep, class Period>
Chris@16 48 bool
Chris@16 49 try_lock_shared_for(const boost::chrono::duration<Rep, Period>& rel_time);
Chris@16 50 template <class Clock, class Duration>
Chris@16 51 bool
Chris@16 52 try_lock_shared_until(
Chris@16 53 const boost::chrono::time_point<Clock, Duration>& abs_time);
Chris@16 54 void unlock_shared();
Chris@16 55 };
Chris@16 56
Chris@16 57 class upgrade_mutex
Chris@16 58 {
Chris@16 59 public:
Chris@16 60
Chris@16 61 upgrade_mutex();
Chris@16 62 ~upgrade_mutex();
Chris@16 63
Chris@16 64 upgrade_mutex(const upgrade_mutex&) = delete;
Chris@16 65 upgrade_mutex& operator=(const upgrade_mutex&) = delete;
Chris@16 66
Chris@16 67 // Exclusive ownership
Chris@16 68
Chris@16 69 void lock();
Chris@16 70 bool try_lock();
Chris@16 71 template <class Rep, class Period>
Chris@16 72 bool try_lock_for(const boost::chrono::duration<Rep, Period>& rel_time);
Chris@16 73 template <class Clock, class Duration>
Chris@16 74 bool
Chris@16 75 try_lock_until(
Chris@16 76 const boost::chrono::time_point<Clock, Duration>& abs_time);
Chris@16 77 void unlock();
Chris@16 78
Chris@16 79 // Shared ownership
Chris@16 80
Chris@16 81 void lock_shared();
Chris@16 82 bool try_lock_shared();
Chris@16 83 template <class Rep, class Period>
Chris@16 84 bool
Chris@16 85 try_lock_shared_for(const boost::chrono::duration<Rep, Period>& rel_time);
Chris@16 86 template <class Clock, class Duration>
Chris@16 87 bool
Chris@16 88 try_lock_shared_until(
Chris@16 89 const boost::chrono::time_point<Clock, Duration>& abs_time);
Chris@16 90 void unlock_shared();
Chris@16 91
Chris@16 92 // Upgrade ownership
Chris@16 93
Chris@16 94 void lock_upgrade();
Chris@16 95 bool try_lock_upgrade();
Chris@16 96 template <class Rep, class Period>
Chris@16 97 bool
Chris@16 98 try_lock_upgrade_for(
Chris@16 99 const boost::chrono::duration<Rep, Period>& rel_time);
Chris@16 100 template <class Clock, class Duration>
Chris@16 101 bool
Chris@16 102 try_lock_upgrade_until(
Chris@16 103 const boost::chrono::time_point<Clock, Duration>& abs_time);
Chris@16 104 void unlock_upgrade();
Chris@16 105
Chris@16 106 // Shared <-> Exclusive
Chris@16 107
Chris@16 108 bool try_unlock_shared_and_lock();
Chris@16 109 template <class Rep, class Period>
Chris@16 110 bool
Chris@16 111 try_unlock_shared_and_lock_for(
Chris@16 112 const boost::chrono::duration<Rep, Period>& rel_time);
Chris@16 113 template <class Clock, class Duration>
Chris@16 114 bool
Chris@16 115 try_unlock_shared_and_lock_until(
Chris@16 116 const boost::chrono::time_point<Clock, Duration>& abs_time);
Chris@16 117 void unlock_and_lock_shared();
Chris@16 118
Chris@16 119 // Shared <-> Upgrade
Chris@16 120
Chris@16 121 bool try_unlock_shared_and_lock_upgrade();
Chris@16 122 template <class Rep, class Period>
Chris@16 123 bool
Chris@16 124 try_unlock_shared_and_lock_upgrade_for(
Chris@16 125 const boost::chrono::duration<Rep, Period>& rel_time);
Chris@16 126 template <class Clock, class Duration>
Chris@16 127 bool
Chris@16 128 try_unlock_shared_and_lock_upgrade_until(
Chris@16 129 const boost::chrono::time_point<Clock, Duration>& abs_time);
Chris@16 130 void unlock_upgrade_and_lock_shared();
Chris@16 131
Chris@16 132 // Upgrade <-> Exclusive
Chris@16 133
Chris@16 134 void unlock_upgrade_and_lock();
Chris@16 135 bool try_unlock_upgrade_and_lock();
Chris@16 136 template <class Rep, class Period>
Chris@16 137 bool
Chris@16 138 try_unlock_upgrade_and_lock_for(
Chris@16 139 const boost::chrono::duration<Rep, Period>& rel_time);
Chris@16 140 template <class Clock, class Duration>
Chris@16 141 bool
Chris@16 142 try_unlock_upgrade_and_lock_until(
Chris@16 143 const boost::chrono::time_point<Clock, Duration>& abs_time);
Chris@16 144 void unlock_and_lock_upgrade();
Chris@16 145 };
Chris@16 146
Chris@16 147 } // thread_v2
Chris@16 148 } // boost
Chris@16 149
Chris@16 150 */
Chris@16 151
Chris@16 152 #include <boost/thread/detail/config.hpp>
Chris@16 153 #include <boost/thread/mutex.hpp>
Chris@16 154 #include <boost/thread/condition_variable.hpp>
Chris@16 155 #include <boost/thread/mutex.hpp>
Chris@16 156 #include <boost/chrono.hpp>
Chris@16 157 #include <climits>
Chris@16 158 #include <boost/system/system_error.hpp>
Chris@16 159 #define BOOST_THREAD_INLINE inline
Chris@16 160
Chris@16 161 namespace boost {
Chris@16 162 namespace thread_v2 {
Chris@16 163
Chris@16 164 class shared_mutex
Chris@16 165 {
Chris@16 166 typedef ::boost::mutex mutex_t;
Chris@16 167 typedef ::boost::condition_variable cond_t;
Chris@16 168 typedef unsigned count_t;
Chris@16 169
Chris@16 170 mutex_t mut_;
Chris@16 171 cond_t gate1_;
Chris@16 172 cond_t gate2_;
Chris@16 173 count_t state_;
Chris@16 174
Chris@16 175 static const count_t write_entered_ = 1U << (sizeof(count_t)*CHAR_BIT - 1);
Chris@16 176 static const count_t n_readers_ = ~write_entered_;
Chris@16 177
Chris@16 178 public:
Chris@16 179 BOOST_THREAD_INLINE shared_mutex();
Chris@16 180 BOOST_THREAD_INLINE ~shared_mutex();
Chris@16 181
Chris@16 182 #ifndef BOOST_NO_CXX11_DELETED_FUNCTIONS
Chris@16 183 shared_mutex(shared_mutex const&) = delete;
Chris@16 184 shared_mutex& operator=(shared_mutex const&) = delete;
Chris@16 185 #else // BOOST_NO_CXX11_DELETED_FUNCTIONS
Chris@16 186 private:
Chris@16 187 shared_mutex(shared_mutex const&);
Chris@16 188 shared_mutex& operator=(shared_mutex const&);
Chris@16 189 public:
Chris@16 190 #endif // BOOST_NO_CXX11_DELETED_FUNCTIONS
Chris@16 191
Chris@16 192 // Exclusive ownership
Chris@16 193
Chris@16 194 BOOST_THREAD_INLINE void lock();
Chris@16 195 BOOST_THREAD_INLINE bool try_lock();
Chris@16 196 template <class Rep, class Period>
Chris@16 197 bool try_lock_for(const boost::chrono::duration<Rep, Period>& rel_time)
Chris@16 198 {
Chris@16 199 return try_lock_until(boost::chrono::steady_clock::now() + rel_time);
Chris@16 200 }
Chris@16 201 template <class Clock, class Duration>
Chris@16 202 bool
Chris@16 203 try_lock_until(
Chris@16 204 const boost::chrono::time_point<Clock, Duration>& abs_time);
Chris@16 205 BOOST_THREAD_INLINE void unlock();
Chris@16 206
Chris@16 207
Chris@16 208 // Shared ownership
Chris@16 209
Chris@16 210 BOOST_THREAD_INLINE void lock_shared();
Chris@16 211 BOOST_THREAD_INLINE bool try_lock_shared();
Chris@16 212 template <class Rep, class Period>
Chris@16 213 bool
Chris@16 214 try_lock_shared_for(const boost::chrono::duration<Rep, Period>& rel_time)
Chris@16 215 {
Chris@16 216 return try_lock_shared_until(boost::chrono::steady_clock::now() +
Chris@16 217 rel_time);
Chris@16 218 }
Chris@16 219 template <class Clock, class Duration>
Chris@16 220 bool
Chris@16 221 try_lock_shared_until(
Chris@16 222 const boost::chrono::time_point<Clock, Duration>& abs_time);
Chris@16 223 BOOST_THREAD_INLINE void unlock_shared();
Chris@16 224
Chris@16 225 #if defined BOOST_THREAD_USES_DATETIME
Chris@16 226 bool timed_lock(system_time const& timeout);
Chris@16 227 template<typename TimeDuration>
Chris@16 228 bool timed_lock(TimeDuration const & relative_time)
Chris@16 229 {
Chris@16 230 return timed_lock(get_system_time()+relative_time);
Chris@16 231 }
Chris@16 232 bool timed_lock_shared(system_time const& timeout);
Chris@16 233 template<typename TimeDuration>
Chris@16 234 bool timed_lock_shared(TimeDuration const & relative_time)
Chris@16 235 {
Chris@16 236 return timed_lock_shared(get_system_time()+relative_time);
Chris@16 237 }
Chris@16 238 #endif
Chris@16 239 };
Chris@16 240
Chris@16 241 template <class Clock, class Duration>
Chris@16 242 bool
Chris@16 243 shared_mutex::try_lock_until(
Chris@16 244 const boost::chrono::time_point<Clock, Duration>& abs_time)
Chris@16 245 {
Chris@16 246 boost::unique_lock<mutex_t> lk(mut_);
Chris@16 247 if (state_ & write_entered_)
Chris@16 248 {
Chris@16 249 while (true)
Chris@16 250 {
Chris@16 251 boost::cv_status status = gate1_.wait_until(lk, abs_time);
Chris@16 252 if ((state_ & write_entered_) == 0)
Chris@16 253 break;
Chris@16 254 if (status == boost::cv_status::timeout)
Chris@16 255 return false;
Chris@16 256 }
Chris@16 257 }
Chris@16 258 state_ |= write_entered_;
Chris@16 259 if (state_ & n_readers_)
Chris@16 260 {
Chris@16 261 while (true)
Chris@16 262 {
Chris@16 263 boost::cv_status status = gate2_.wait_until(lk, abs_time);
Chris@16 264 if ((state_ & n_readers_) == 0)
Chris@16 265 break;
Chris@16 266 if (status == boost::cv_status::timeout)
Chris@16 267 {
Chris@16 268 state_ &= ~write_entered_;
Chris@16 269 return false;
Chris@16 270 }
Chris@16 271 }
Chris@16 272 }
Chris@16 273 return true;
Chris@16 274 }
Chris@16 275
Chris@16 276 template <class Clock, class Duration>
Chris@16 277 bool
Chris@16 278 shared_mutex::try_lock_shared_until(
Chris@16 279 const boost::chrono::time_point<Clock, Duration>& abs_time)
Chris@16 280 {
Chris@16 281 boost::unique_lock<mutex_t> lk(mut_);
Chris@16 282 if ((state_ & write_entered_) || (state_ & n_readers_) == n_readers_)
Chris@16 283 {
Chris@16 284 while (true)
Chris@16 285 {
Chris@16 286 boost::cv_status status = gate1_.wait_until(lk, abs_time);
Chris@16 287 if ((state_ & write_entered_) == 0 &&
Chris@16 288 (state_ & n_readers_) < n_readers_)
Chris@16 289 break;
Chris@16 290 if (status == boost::cv_status::timeout)
Chris@16 291 return false;
Chris@16 292 }
Chris@16 293 }
Chris@16 294 count_t num_readers = (state_ & n_readers_) + 1;
Chris@16 295 state_ &= ~n_readers_;
Chris@16 296 state_ |= num_readers;
Chris@16 297 return true;
Chris@16 298 }
Chris@16 299
Chris@16 300 #if defined BOOST_THREAD_USES_DATETIME
Chris@16 301 bool shared_mutex::timed_lock(system_time const& abs_time)
Chris@16 302 {
Chris@16 303 boost::unique_lock<mutex_t> lk(mut_);
Chris@16 304 if (state_ & write_entered_)
Chris@16 305 {
Chris@16 306 while (true)
Chris@16 307 {
Chris@16 308 bool status = gate1_.timed_wait(lk, abs_time);
Chris@16 309 if ((state_ & write_entered_) == 0)
Chris@16 310 break;
Chris@16 311 if (!status)
Chris@16 312 return false;
Chris@16 313 }
Chris@16 314 }
Chris@16 315 state_ |= write_entered_;
Chris@16 316 if (state_ & n_readers_)
Chris@16 317 {
Chris@16 318 while (true)
Chris@16 319 {
Chris@16 320 bool status = gate2_.timed_wait(lk, abs_time);
Chris@16 321 if ((state_ & n_readers_) == 0)
Chris@16 322 break;
Chris@16 323 if (!status)
Chris@16 324 {
Chris@16 325 state_ &= ~write_entered_;
Chris@16 326 return false;
Chris@16 327 }
Chris@16 328 }
Chris@16 329 }
Chris@16 330 return true;
Chris@16 331 }
Chris@16 332 bool shared_mutex::timed_lock_shared(system_time const& abs_time)
Chris@16 333 {
Chris@16 334 boost::unique_lock<mutex_t> lk(mut_);
Chris@16 335 if (state_ & write_entered_)
Chris@16 336 {
Chris@16 337 while (true)
Chris@16 338 {
Chris@16 339 bool status = gate1_.timed_wait(lk, abs_time);
Chris@16 340 if ((state_ & write_entered_) == 0)
Chris@16 341 break;
Chris@16 342 if (!status )
Chris@16 343 return false;
Chris@16 344 }
Chris@16 345 }
Chris@16 346 state_ |= write_entered_;
Chris@16 347 if (state_ & n_readers_)
Chris@16 348 {
Chris@16 349 while (true)
Chris@16 350 {
Chris@16 351 bool status = gate2_.timed_wait(lk, abs_time);
Chris@16 352 if ((state_ & n_readers_) == 0)
Chris@16 353 break;
Chris@16 354 if (!status)
Chris@16 355 {
Chris@16 356 state_ &= ~write_entered_;
Chris@16 357 return false;
Chris@16 358 }
Chris@16 359 }
Chris@16 360 }
Chris@16 361 return true;
Chris@16 362 }
Chris@16 363 #endif
Chris@16 364 class upgrade_mutex
Chris@16 365 {
Chris@16 366 typedef boost::mutex mutex_t;
Chris@16 367 typedef boost::condition_variable cond_t;
Chris@16 368 typedef unsigned count_t;
Chris@16 369
Chris@16 370 mutex_t mut_;
Chris@16 371 cond_t gate1_;
Chris@16 372 cond_t gate2_;
Chris@16 373 count_t state_;
Chris@16 374
Chris@16 375 static const unsigned write_entered_ = 1U << (sizeof(count_t)*CHAR_BIT - 1);
Chris@16 376 static const unsigned upgradable_entered_ = write_entered_ >> 1;
Chris@16 377 static const unsigned n_readers_ = ~(write_entered_ | upgradable_entered_);
Chris@16 378
Chris@16 379 public:
Chris@16 380
Chris@16 381 BOOST_THREAD_INLINE upgrade_mutex();
Chris@16 382 BOOST_THREAD_INLINE ~upgrade_mutex();
Chris@16 383
Chris@16 384 #ifndef BOOST_CXX11_NO_DELETED_FUNCTIONS
Chris@16 385 upgrade_mutex(const upgrade_mutex&) = delete;
Chris@16 386 upgrade_mutex& operator=(const upgrade_mutex&) = delete;
Chris@16 387 #else // BOOST_CXX11_NO_DELETED_FUNCTIONS
Chris@16 388 private:
Chris@16 389 upgrade_mutex(const upgrade_mutex&);
Chris@16 390 upgrade_mutex& operator=(const upgrade_mutex&);
Chris@16 391 public:
Chris@16 392 #endif // BOOST_CXX11_NO_DELETED_FUNCTIONS
Chris@16 393
Chris@16 394 // Exclusive ownership
Chris@16 395
Chris@16 396 BOOST_THREAD_INLINE void lock();
Chris@16 397 BOOST_THREAD_INLINE bool try_lock();
Chris@16 398 template <class Rep, class Period>
Chris@16 399 bool try_lock_for(const boost::chrono::duration<Rep, Period>& rel_time)
Chris@16 400 {
Chris@16 401 return try_lock_until(boost::chrono::steady_clock::now() + rel_time);
Chris@16 402 }
Chris@16 403 template <class Clock, class Duration>
Chris@16 404 bool
Chris@16 405 try_lock_until(
Chris@16 406 const boost::chrono::time_point<Clock, Duration>& abs_time);
Chris@16 407 BOOST_THREAD_INLINE void unlock();
Chris@16 408
Chris@16 409 // Shared ownership
Chris@16 410
Chris@16 411 BOOST_THREAD_INLINE void lock_shared();
Chris@16 412 BOOST_THREAD_INLINE bool try_lock_shared();
Chris@16 413 template <class Rep, class Period>
Chris@16 414 bool
Chris@16 415 try_lock_shared_for(const boost::chrono::duration<Rep, Period>& rel_time)
Chris@16 416 {
Chris@16 417 return try_lock_shared_until(boost::chrono::steady_clock::now() +
Chris@16 418 rel_time);
Chris@16 419 }
Chris@16 420 template <class Clock, class Duration>
Chris@16 421 bool
Chris@16 422 try_lock_shared_until(
Chris@16 423 const boost::chrono::time_point<Clock, Duration>& abs_time);
Chris@16 424 BOOST_THREAD_INLINE void unlock_shared();
Chris@16 425
Chris@16 426 // Upgrade ownership
Chris@16 427
Chris@16 428 BOOST_THREAD_INLINE void lock_upgrade();
Chris@16 429 BOOST_THREAD_INLINE bool try_lock_upgrade();
Chris@16 430 template <class Rep, class Period>
Chris@16 431 bool
Chris@16 432 try_lock_upgrade_for(
Chris@16 433 const boost::chrono::duration<Rep, Period>& rel_time)
Chris@16 434 {
Chris@16 435 return try_lock_upgrade_until(boost::chrono::steady_clock::now() +
Chris@16 436 rel_time);
Chris@16 437 }
Chris@16 438 template <class Clock, class Duration>
Chris@16 439 bool
Chris@16 440 try_lock_upgrade_until(
Chris@16 441 const boost::chrono::time_point<Clock, Duration>& abs_time);
Chris@16 442 BOOST_THREAD_INLINE void unlock_upgrade();
Chris@16 443
Chris@16 444 // Shared <-> Exclusive
Chris@16 445
Chris@16 446 BOOST_THREAD_INLINE bool try_unlock_shared_and_lock();
Chris@16 447 template <class Rep, class Period>
Chris@16 448 bool
Chris@16 449 try_unlock_shared_and_lock_for(
Chris@16 450 const boost::chrono::duration<Rep, Period>& rel_time)
Chris@16 451 {
Chris@16 452 return try_unlock_shared_and_lock_until(
Chris@16 453 boost::chrono::steady_clock::now() + rel_time);
Chris@16 454 }
Chris@16 455 template <class Clock, class Duration>
Chris@16 456 bool
Chris@16 457 try_unlock_shared_and_lock_until(
Chris@16 458 const boost::chrono::time_point<Clock, Duration>& abs_time);
Chris@16 459 BOOST_THREAD_INLINE void unlock_and_lock_shared();
Chris@16 460
Chris@16 461 // Shared <-> Upgrade
Chris@16 462
Chris@16 463 BOOST_THREAD_INLINE bool try_unlock_shared_and_lock_upgrade();
Chris@16 464 template <class Rep, class Period>
Chris@16 465 bool
Chris@16 466 try_unlock_shared_and_lock_upgrade_for(
Chris@16 467 const boost::chrono::duration<Rep, Period>& rel_time)
Chris@16 468 {
Chris@16 469 return try_unlock_shared_and_lock_upgrade_until(
Chris@16 470 boost::chrono::steady_clock::now() + rel_time);
Chris@16 471 }
Chris@16 472 template <class Clock, class Duration>
Chris@16 473 bool
Chris@16 474 try_unlock_shared_and_lock_upgrade_until(
Chris@16 475 const boost::chrono::time_point<Clock, Duration>& abs_time);
Chris@16 476 BOOST_THREAD_INLINE void unlock_upgrade_and_lock_shared();
Chris@16 477
Chris@16 478 // Upgrade <-> Exclusive
Chris@16 479
Chris@16 480 BOOST_THREAD_INLINE void unlock_upgrade_and_lock();
Chris@16 481 BOOST_THREAD_INLINE bool try_unlock_upgrade_and_lock();
Chris@16 482 template <class Rep, class Period>
Chris@16 483 bool
Chris@16 484 try_unlock_upgrade_and_lock_for(
Chris@16 485 const boost::chrono::duration<Rep, Period>& rel_time)
Chris@16 486 {
Chris@16 487 return try_unlock_upgrade_and_lock_until(
Chris@16 488 boost::chrono::steady_clock::now() + rel_time);
Chris@16 489 }
Chris@16 490 template <class Clock, class Duration>
Chris@16 491 bool
Chris@16 492 try_unlock_upgrade_and_lock_until(
Chris@16 493 const boost::chrono::time_point<Clock, Duration>& abs_time);
Chris@16 494 BOOST_THREAD_INLINE void unlock_and_lock_upgrade();
Chris@16 495
Chris@16 496 #if defined BOOST_THREAD_USES_DATETIME
Chris@16 497 inline bool timed_lock(system_time const& abs_time);
Chris@16 498 template<typename TimeDuration>
Chris@16 499 bool timed_lock(TimeDuration const & relative_time)
Chris@16 500 {
Chris@16 501 return timed_lock(get_system_time()+relative_time);
Chris@16 502 }
Chris@16 503 inline bool timed_lock_shared(system_time const& abs_time);
Chris@16 504 template<typename TimeDuration>
Chris@16 505 bool timed_lock_shared(TimeDuration const & relative_time)
Chris@16 506 {
Chris@16 507 return timed_lock_shared(get_system_time()+relative_time);
Chris@16 508 }
Chris@16 509 inline bool timed_lock_upgrade(system_time const& abs_time);
Chris@16 510 template<typename TimeDuration>
Chris@16 511 bool timed_lock_upgrade(TimeDuration const & relative_time)
Chris@16 512 {
Chris@16 513 return timed_lock_upgrade(get_system_time()+relative_time);
Chris@16 514 }
Chris@16 515 #endif
Chris@16 516
Chris@16 517 };
Chris@16 518
Chris@16 519 template <class Clock, class Duration>
Chris@16 520 bool
Chris@16 521 upgrade_mutex::try_lock_until(
Chris@16 522 const boost::chrono::time_point<Clock, Duration>& abs_time)
Chris@16 523 {
Chris@16 524 boost::unique_lock<mutex_t> lk(mut_);
Chris@16 525 if (state_ & (write_entered_ | upgradable_entered_))
Chris@16 526 {
Chris@16 527 while (true)
Chris@16 528 {
Chris@16 529 boost::cv_status status = gate1_.wait_until(lk, abs_time);
Chris@16 530 if ((state_ & (write_entered_ | upgradable_entered_)) == 0)
Chris@16 531 break;
Chris@16 532 if (status == boost::cv_status::timeout)
Chris@16 533 return false;
Chris@16 534 }
Chris@16 535 }
Chris@16 536 state_ |= write_entered_;
Chris@16 537 if (state_ & n_readers_)
Chris@16 538 {
Chris@16 539 while (true)
Chris@16 540 {
Chris@16 541 boost::cv_status status = gate2_.wait_until(lk, abs_time);
Chris@16 542 if ((state_ & n_readers_) == 0)
Chris@16 543 break;
Chris@16 544 if (status == boost::cv_status::timeout)
Chris@16 545 {
Chris@16 546 state_ &= ~write_entered_;
Chris@16 547 return false;
Chris@16 548 }
Chris@16 549 }
Chris@16 550 }
Chris@16 551 return true;
Chris@16 552 }
Chris@16 553
Chris@16 554 template <class Clock, class Duration>
Chris@16 555 bool
Chris@16 556 upgrade_mutex::try_lock_shared_until(
Chris@16 557 const boost::chrono::time_point<Clock, Duration>& abs_time)
Chris@16 558 {
Chris@16 559 boost::unique_lock<mutex_t> lk(mut_);
Chris@16 560 if ((state_ & write_entered_) || (state_ & n_readers_) == n_readers_)
Chris@16 561 {
Chris@16 562 while (true)
Chris@16 563 {
Chris@16 564 boost::cv_status status = gate1_.wait_until(lk, abs_time);
Chris@16 565 if ((state_ & write_entered_) == 0 &&
Chris@16 566 (state_ & n_readers_) < n_readers_)
Chris@16 567 break;
Chris@16 568 if (status == boost::cv_status::timeout)
Chris@16 569 return false;
Chris@16 570 }
Chris@16 571 }
Chris@16 572 count_t num_readers = (state_ & n_readers_) + 1;
Chris@16 573 state_ &= ~n_readers_;
Chris@16 574 state_ |= num_readers;
Chris@16 575 return true;
Chris@16 576 }
Chris@16 577
Chris@16 578 template <class Clock, class Duration>
Chris@16 579 bool
Chris@16 580 upgrade_mutex::try_lock_upgrade_until(
Chris@16 581 const boost::chrono::time_point<Clock, Duration>& abs_time)
Chris@16 582 {
Chris@16 583 boost::unique_lock<mutex_t> lk(mut_);
Chris@16 584 if ((state_ & (write_entered_ | upgradable_entered_)) ||
Chris@16 585 (state_ & n_readers_) == n_readers_)
Chris@16 586 {
Chris@16 587 while (true)
Chris@16 588 {
Chris@16 589 boost::cv_status status = gate1_.wait_until(lk, abs_time);
Chris@16 590 if ((state_ & (write_entered_ | upgradable_entered_)) == 0 &&
Chris@16 591 (state_ & n_readers_) < n_readers_)
Chris@16 592 break;
Chris@16 593 if (status == boost::cv_status::timeout)
Chris@16 594 return false;
Chris@16 595 }
Chris@16 596 }
Chris@16 597 count_t num_readers = (state_ & n_readers_) + 1;
Chris@16 598 state_ &= ~n_readers_;
Chris@16 599 state_ |= upgradable_entered_ | num_readers;
Chris@16 600 return true;
Chris@16 601 }
Chris@16 602
Chris@16 603 #if defined BOOST_THREAD_USES_DATETIME
Chris@16 604 bool upgrade_mutex::timed_lock(system_time const& abs_time)
Chris@16 605 {
Chris@16 606 boost::unique_lock<mutex_t> lk(mut_);
Chris@16 607 if (state_ & (write_entered_ | upgradable_entered_))
Chris@16 608 {
Chris@16 609 while (true)
Chris@16 610 {
Chris@16 611 bool status = gate1_.timed_wait(lk, abs_time);
Chris@16 612 if ((state_ & (write_entered_ | upgradable_entered_)) == 0)
Chris@16 613 break;
Chris@16 614 if (!status)
Chris@16 615 return false;
Chris@16 616 }
Chris@16 617 }
Chris@16 618 state_ |= write_entered_;
Chris@16 619 if (state_ & n_readers_)
Chris@16 620 {
Chris@16 621 while (true)
Chris@16 622 {
Chris@16 623 bool status = gate2_.timed_wait(lk, abs_time);
Chris@16 624 if ((state_ & n_readers_) == 0)
Chris@16 625 break;
Chris@16 626 if (!status)
Chris@16 627 {
Chris@16 628 state_ &= ~write_entered_;
Chris@16 629 return false;
Chris@16 630 }
Chris@16 631 }
Chris@16 632 }
Chris@16 633 return true;
Chris@16 634 }
Chris@16 635 bool upgrade_mutex::timed_lock_shared(system_time const& abs_time)
Chris@16 636 {
Chris@16 637 boost::unique_lock<mutex_t> lk(mut_);
Chris@16 638 if ((state_ & write_entered_) || (state_ & n_readers_) == n_readers_)
Chris@16 639 {
Chris@16 640 while (true)
Chris@16 641 {
Chris@16 642 bool status = gate1_.timed_wait(lk, abs_time);
Chris@16 643 if ((state_ & write_entered_) == 0 &&
Chris@16 644 (state_ & n_readers_) < n_readers_)
Chris@16 645 break;
Chris@16 646 if (!status)
Chris@16 647 return false;
Chris@16 648 }
Chris@16 649 }
Chris@16 650 count_t num_readers = (state_ & n_readers_) + 1;
Chris@16 651 state_ &= ~n_readers_;
Chris@16 652 state_ |= num_readers;
Chris@16 653 return true;
Chris@16 654 }
Chris@16 655 bool upgrade_mutex::timed_lock_upgrade(system_time const& abs_time)
Chris@16 656 {
Chris@16 657 boost::unique_lock<mutex_t> lk(mut_);
Chris@16 658 if ((state_ & (write_entered_ | upgradable_entered_)) ||
Chris@16 659 (state_ & n_readers_) == n_readers_)
Chris@16 660 {
Chris@16 661 while (true)
Chris@16 662 {
Chris@16 663 bool status = gate1_.timed_wait(lk, abs_time);
Chris@16 664 if ((state_ & (write_entered_ | upgradable_entered_)) == 0 &&
Chris@16 665 (state_ & n_readers_) < n_readers_)
Chris@16 666 break;
Chris@16 667 if (!status)
Chris@16 668 return false;
Chris@16 669 }
Chris@16 670 }
Chris@16 671 count_t num_readers = (state_ & n_readers_) + 1;
Chris@16 672 state_ &= ~n_readers_;
Chris@16 673 state_ |= upgradable_entered_ | num_readers;
Chris@16 674 return true;
Chris@16 675 }
Chris@16 676
Chris@16 677 #endif
Chris@16 678 template <class Clock, class Duration>
Chris@16 679 bool
Chris@16 680 upgrade_mutex::try_unlock_shared_and_lock_until(
Chris@16 681 const boost::chrono::time_point<Clock, Duration>& abs_time)
Chris@16 682 {
Chris@16 683 boost::unique_lock<mutex_t> lk(mut_);
Chris@16 684 if (state_ != 1)
Chris@16 685 {
Chris@16 686 while (true)
Chris@16 687 {
Chris@16 688 boost::cv_status status = gate2_.wait_until(lk, abs_time);
Chris@16 689 if (state_ == 1)
Chris@16 690 break;
Chris@16 691 if (status == boost::cv_status::timeout)
Chris@16 692 return false;
Chris@16 693 }
Chris@16 694 }
Chris@16 695 state_ = write_entered_;
Chris@16 696 return true;
Chris@16 697 }
Chris@16 698
Chris@16 699 template <class Clock, class Duration>
Chris@16 700 bool
Chris@16 701 upgrade_mutex::try_unlock_shared_and_lock_upgrade_until(
Chris@16 702 const boost::chrono::time_point<Clock, Duration>& abs_time)
Chris@16 703 {
Chris@16 704 boost::unique_lock<mutex_t> lk(mut_);
Chris@16 705 if ((state_ & (write_entered_ | upgradable_entered_)) != 0)
Chris@16 706 {
Chris@16 707 while (true)
Chris@16 708 {
Chris@16 709 boost::cv_status status = gate2_.wait_until(lk, abs_time);
Chris@16 710 if ((state_ & (write_entered_ | upgradable_entered_)) == 0)
Chris@16 711 break;
Chris@16 712 if (status == boost::cv_status::timeout)
Chris@16 713 return false;
Chris@16 714 }
Chris@16 715 }
Chris@16 716 state_ |= upgradable_entered_;
Chris@16 717 return true;
Chris@16 718 }
Chris@16 719
Chris@16 720 template <class Clock, class Duration>
Chris@16 721 bool
Chris@16 722 upgrade_mutex::try_unlock_upgrade_and_lock_until(
Chris@16 723 const boost::chrono::time_point<Clock, Duration>& abs_time)
Chris@16 724 {
Chris@16 725 boost::unique_lock<mutex_t> lk(mut_);
Chris@16 726 if ((state_ & n_readers_) != 1)
Chris@16 727 {
Chris@16 728 while (true)
Chris@16 729 {
Chris@16 730 boost::cv_status status = gate2_.wait_until(lk, abs_time);
Chris@16 731 if ((state_ & n_readers_) == 1)
Chris@16 732 break;
Chris@16 733 if (status == boost::cv_status::timeout)
Chris@16 734 return false;
Chris@16 735 }
Chris@16 736 }
Chris@16 737 state_ = write_entered_;
Chris@16 738 return true;
Chris@16 739 }
Chris@16 740
Chris@16 741 //////
Chris@16 742 // shared_mutex
Chris@16 743
Chris@16 744 shared_mutex::shared_mutex()
Chris@16 745 : state_(0)
Chris@16 746 {
Chris@16 747 }
Chris@16 748
Chris@16 749 shared_mutex::~shared_mutex()
Chris@16 750 {
Chris@16 751 boost::lock_guard<mutex_t> _(mut_);
Chris@16 752 }
Chris@16 753
Chris@16 754 // Exclusive ownership
Chris@16 755
Chris@16 756 void
Chris@16 757 shared_mutex::lock()
Chris@16 758 {
Chris@16 759 boost::unique_lock<mutex_t> lk(mut_);
Chris@16 760 while (state_ & write_entered_)
Chris@16 761 gate1_.wait(lk);
Chris@16 762 state_ |= write_entered_;
Chris@16 763 while (state_ & n_readers_)
Chris@16 764 gate2_.wait(lk);
Chris@16 765 }
Chris@16 766
Chris@16 767 bool
Chris@16 768 shared_mutex::try_lock()
Chris@16 769 {
Chris@16 770 boost::unique_lock<mutex_t> lk(mut_);
Chris@16 771 if (state_ == 0)
Chris@16 772 {
Chris@16 773 state_ = write_entered_;
Chris@16 774 return true;
Chris@16 775 }
Chris@16 776 return false;
Chris@16 777 }
Chris@16 778
Chris@16 779 void
Chris@16 780 shared_mutex::unlock()
Chris@16 781 {
Chris@16 782 boost::lock_guard<mutex_t> _(mut_);
Chris@16 783 state_ = 0;
Chris@16 784 gate1_.notify_all();
Chris@16 785 }
Chris@16 786
Chris@16 787 // Shared ownership
Chris@16 788
Chris@16 789 void
Chris@16 790 shared_mutex::lock_shared()
Chris@16 791 {
Chris@16 792 boost::unique_lock<mutex_t> lk(mut_);
Chris@16 793 while ((state_ & write_entered_) || (state_ & n_readers_) == n_readers_)
Chris@16 794 gate1_.wait(lk);
Chris@16 795 count_t num_readers = (state_ & n_readers_) + 1;
Chris@16 796 state_ &= ~n_readers_;
Chris@16 797 state_ |= num_readers;
Chris@16 798 }
Chris@16 799
Chris@16 800 bool
Chris@16 801 shared_mutex::try_lock_shared()
Chris@16 802 {
Chris@16 803 boost::unique_lock<mutex_t> lk(mut_);
Chris@16 804 count_t num_readers = state_ & n_readers_;
Chris@16 805 if (!(state_ & write_entered_) && num_readers != n_readers_)
Chris@16 806 {
Chris@16 807 ++num_readers;
Chris@16 808 state_ &= ~n_readers_;
Chris@16 809 state_ |= num_readers;
Chris@16 810 return true;
Chris@16 811 }
Chris@16 812 return false;
Chris@16 813 }
Chris@16 814
Chris@16 815 void
Chris@16 816 shared_mutex::unlock_shared()
Chris@16 817 {
Chris@16 818 boost::lock_guard<mutex_t> _(mut_);
Chris@16 819 count_t num_readers = (state_ & n_readers_) - 1;
Chris@16 820 state_ &= ~n_readers_;
Chris@16 821 state_ |= num_readers;
Chris@16 822 if (state_ & write_entered_)
Chris@16 823 {
Chris@16 824 if (num_readers == 0)
Chris@16 825 gate2_.notify_one();
Chris@16 826 }
Chris@16 827 else
Chris@16 828 {
Chris@16 829 if (num_readers == n_readers_ - 1)
Chris@16 830 gate1_.notify_one();
Chris@16 831 }
Chris@16 832 }
Chris@16 833
Chris@16 834 // upgrade_mutex
Chris@16 835
Chris@16 836 upgrade_mutex::upgrade_mutex()
Chris@16 837 : gate1_(),
Chris@16 838 gate2_(),
Chris@16 839 state_(0)
Chris@16 840 {
Chris@16 841 }
Chris@16 842
Chris@16 843 upgrade_mutex::~upgrade_mutex()
Chris@16 844 {
Chris@16 845 boost::lock_guard<mutex_t> _(mut_);
Chris@16 846 }
Chris@16 847
Chris@16 848 // Exclusive ownership
Chris@16 849
Chris@16 850 void
Chris@16 851 upgrade_mutex::lock()
Chris@16 852 {
Chris@16 853 boost::unique_lock<mutex_t> lk(mut_);
Chris@16 854 while (state_ & (write_entered_ | upgradable_entered_))
Chris@16 855 gate1_.wait(lk);
Chris@16 856 state_ |= write_entered_;
Chris@16 857 while (state_ & n_readers_)
Chris@16 858 gate2_.wait(lk);
Chris@16 859 }
Chris@16 860
Chris@16 861 bool
Chris@16 862 upgrade_mutex::try_lock()
Chris@16 863 {
Chris@16 864 boost::unique_lock<mutex_t> lk(mut_);
Chris@16 865 if (state_ == 0)
Chris@16 866 {
Chris@16 867 state_ = write_entered_;
Chris@16 868 return true;
Chris@16 869 }
Chris@16 870 return false;
Chris@16 871 }
Chris@16 872
Chris@16 873 void
Chris@16 874 upgrade_mutex::unlock()
Chris@16 875 {
Chris@16 876 boost::lock_guard<mutex_t> _(mut_);
Chris@16 877 state_ = 0;
Chris@16 878 gate1_.notify_all();
Chris@16 879 }
Chris@16 880
Chris@16 881 // Shared ownership
Chris@16 882
Chris@16 883 void
Chris@16 884 upgrade_mutex::lock_shared()
Chris@16 885 {
Chris@16 886 boost::unique_lock<mutex_t> lk(mut_);
Chris@16 887 while ((state_ & write_entered_) || (state_ & n_readers_) == n_readers_)
Chris@16 888 gate1_.wait(lk);
Chris@16 889 count_t num_readers = (state_ & n_readers_) + 1;
Chris@16 890 state_ &= ~n_readers_;
Chris@16 891 state_ |= num_readers;
Chris@16 892 }
Chris@16 893
Chris@16 894 bool
Chris@16 895 upgrade_mutex::try_lock_shared()
Chris@16 896 {
Chris@16 897 boost::unique_lock<mutex_t> lk(mut_);
Chris@16 898 count_t num_readers = state_ & n_readers_;
Chris@16 899 if (!(state_ & write_entered_) && num_readers != n_readers_)
Chris@16 900 {
Chris@16 901 ++num_readers;
Chris@16 902 state_ &= ~n_readers_;
Chris@16 903 state_ |= num_readers;
Chris@16 904 return true;
Chris@16 905 }
Chris@16 906 return false;
Chris@16 907 }
Chris@16 908
Chris@16 909 void
Chris@16 910 upgrade_mutex::unlock_shared()
Chris@16 911 {
Chris@16 912 boost::lock_guard<mutex_t> _(mut_);
Chris@16 913 count_t num_readers = (state_ & n_readers_) - 1;
Chris@16 914 state_ &= ~n_readers_;
Chris@16 915 state_ |= num_readers;
Chris@16 916 if (state_ & write_entered_)
Chris@16 917 {
Chris@16 918 if (num_readers == 0)
Chris@16 919 gate2_.notify_one();
Chris@16 920 }
Chris@16 921 else
Chris@16 922 {
Chris@16 923 if (num_readers == n_readers_ - 1)
Chris@16 924 gate1_.notify_one();
Chris@16 925 }
Chris@16 926 }
Chris@16 927
Chris@16 928 // Upgrade ownership
Chris@16 929
Chris@16 930 void
Chris@16 931 upgrade_mutex::lock_upgrade()
Chris@16 932 {
Chris@16 933 boost::unique_lock<mutex_t> lk(mut_);
Chris@16 934 while ((state_ & (write_entered_ | upgradable_entered_)) ||
Chris@16 935 (state_ & n_readers_) == n_readers_)
Chris@16 936 gate1_.wait(lk);
Chris@16 937 count_t num_readers = (state_ & n_readers_) + 1;
Chris@16 938 state_ &= ~n_readers_;
Chris@16 939 state_ |= upgradable_entered_ | num_readers;
Chris@16 940 }
Chris@16 941
Chris@16 942 bool
Chris@16 943 upgrade_mutex::try_lock_upgrade()
Chris@16 944 {
Chris@16 945 boost::unique_lock<mutex_t> lk(mut_);
Chris@16 946 count_t num_readers = state_ & n_readers_;
Chris@16 947 if (!(state_ & (write_entered_ | upgradable_entered_))
Chris@16 948 && num_readers != n_readers_)
Chris@16 949 {
Chris@16 950 ++num_readers;
Chris@16 951 state_ &= ~n_readers_;
Chris@16 952 state_ |= upgradable_entered_ | num_readers;
Chris@16 953 return true;
Chris@16 954 }
Chris@16 955 return false;
Chris@16 956 }
Chris@16 957
Chris@16 958 void
Chris@16 959 upgrade_mutex::unlock_upgrade()
Chris@16 960 {
Chris@16 961 {
Chris@16 962 boost::lock_guard<mutex_t> _(mut_);
Chris@16 963 count_t num_readers = (state_ & n_readers_) - 1;
Chris@16 964 state_ &= ~(upgradable_entered_ | n_readers_);
Chris@16 965 state_ |= num_readers;
Chris@16 966 }
Chris@16 967 gate1_.notify_all();
Chris@16 968 }
Chris@16 969
Chris@16 970 // Shared <-> Exclusive
Chris@16 971
Chris@16 972 bool
Chris@16 973 upgrade_mutex::try_unlock_shared_and_lock()
Chris@16 974 {
Chris@16 975 boost::unique_lock<mutex_t> lk(mut_);
Chris@16 976 if (state_ == 1)
Chris@16 977 {
Chris@16 978 state_ = write_entered_;
Chris@16 979 return true;
Chris@16 980 }
Chris@16 981 return false;
Chris@16 982 }
Chris@16 983
Chris@16 984 void
Chris@16 985 upgrade_mutex::unlock_and_lock_shared()
Chris@16 986 {
Chris@16 987 {
Chris@16 988 boost::lock_guard<mutex_t> _(mut_);
Chris@16 989 state_ = 1;
Chris@16 990 }
Chris@16 991 gate1_.notify_all();
Chris@16 992 }
Chris@16 993
Chris@16 994 // Shared <-> Upgrade
Chris@16 995
Chris@16 996 bool
Chris@16 997 upgrade_mutex::try_unlock_shared_and_lock_upgrade()
Chris@16 998 {
Chris@16 999 boost::unique_lock<mutex_t> lk(mut_);
Chris@16 1000 if (!(state_ & (write_entered_ | upgradable_entered_)))
Chris@16 1001 {
Chris@16 1002 state_ |= upgradable_entered_;
Chris@16 1003 return true;
Chris@16 1004 }
Chris@16 1005 return false;
Chris@16 1006 }
Chris@16 1007
Chris@16 1008 void
Chris@16 1009 upgrade_mutex::unlock_upgrade_and_lock_shared()
Chris@16 1010 {
Chris@16 1011 {
Chris@16 1012 boost::lock_guard<mutex_t> _(mut_);
Chris@16 1013 state_ &= ~upgradable_entered_;
Chris@16 1014 }
Chris@16 1015 gate1_.notify_all();
Chris@16 1016 }
Chris@16 1017
Chris@16 1018 // Upgrade <-> Exclusive
Chris@16 1019
Chris@16 1020 void
Chris@16 1021 upgrade_mutex::unlock_upgrade_and_lock()
Chris@16 1022 {
Chris@16 1023 boost::unique_lock<mutex_t> lk(mut_);
Chris@16 1024 count_t num_readers = (state_ & n_readers_) - 1;
Chris@16 1025 state_ &= ~(upgradable_entered_ | n_readers_);
Chris@16 1026 state_ |= write_entered_ | num_readers;
Chris@16 1027 while (state_ & n_readers_)
Chris@16 1028 gate2_.wait(lk);
Chris@16 1029 }
Chris@16 1030
Chris@16 1031 bool
Chris@16 1032 upgrade_mutex::try_unlock_upgrade_and_lock()
Chris@16 1033 {
Chris@16 1034 boost::unique_lock<mutex_t> lk(mut_);
Chris@16 1035 if (state_ == (upgradable_entered_ | 1))
Chris@16 1036 {
Chris@16 1037 state_ = write_entered_;
Chris@16 1038 return true;
Chris@16 1039 }
Chris@16 1040 return false;
Chris@16 1041 }
Chris@16 1042
Chris@16 1043 void
Chris@16 1044 upgrade_mutex::unlock_and_lock_upgrade()
Chris@16 1045 {
Chris@16 1046 {
Chris@16 1047 boost::lock_guard<mutex_t> _(mut_);
Chris@16 1048 state_ = upgradable_entered_ | 1;
Chris@16 1049 }
Chris@16 1050 gate1_.notify_all();
Chris@16 1051 }
Chris@16 1052
Chris@16 1053 } // thread_v2
Chris@16 1054 } // boost
Chris@16 1055
Chris@16 1056 namespace boost {
Chris@16 1057 //using thread_v2::shared_mutex;
Chris@16 1058 using thread_v2::upgrade_mutex;
Chris@16 1059 typedef thread_v2::upgrade_mutex shared_mutex;
Chris@16 1060 }
Chris@16 1061
Chris@16 1062 #endif