annotate DEPENDENCIES/generic/include/boost/thread/pthread/shared_mutex_assert.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_PTHREAD_SHARED_MUTEX_HPP
Chris@16 2 #define BOOST_THREAD_PTHREAD_SHARED_MUTEX_HPP
Chris@16 3
Chris@16 4 // (C) Copyright 2006-8 Anthony Williams
Chris@16 5 // (C) Copyright 2012 Vicente J. Botet Escriba
Chris@16 6 //
Chris@16 7 // Distributed under the Boost Software License, Version 1.0. (See
Chris@16 8 // accompanying file LICENSE_1_0.txt or copy at
Chris@16 9 // http://www.boost.org/LICENSE_1_0.txt)
Chris@16 10
Chris@16 11 #include <boost/assert.hpp>
Chris@16 12 #include <boost/static_assert.hpp>
Chris@16 13 #include <boost/thread/mutex.hpp>
Chris@16 14 #include <boost/thread/condition_variable.hpp>
Chris@16 15 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
Chris@16 16 #include <boost/thread/detail/thread_interruption.hpp>
Chris@16 17 #endif
Chris@16 18 #ifdef BOOST_THREAD_USES_CHRONO
Chris@16 19 #include <boost/chrono/system_clocks.hpp>
Chris@16 20 #include <boost/chrono/ceil.hpp>
Chris@16 21 #endif
Chris@16 22 #include <boost/thread/detail/delete.hpp>
Chris@16 23 #include <boost/assert.hpp>
Chris@16 24
Chris@16 25 #include <boost/config/abi_prefix.hpp>
Chris@16 26
Chris@16 27 namespace boost
Chris@16 28 {
Chris@16 29 class shared_mutex
Chris@16 30 {
Chris@16 31 private:
Chris@16 32 class state_data
Chris@16 33 {
Chris@16 34 public:
Chris@16 35 state_data () :
Chris@16 36 shared_count(0),
Chris@16 37 exclusive(false),
Chris@16 38 upgrade(false),
Chris@16 39 exclusive_waiting_blocked(false)
Chris@16 40 {}
Chris@16 41
Chris@16 42 void assert_free() const
Chris@16 43 {
Chris@16 44 BOOST_ASSERT( ! exclusive );
Chris@16 45 BOOST_ASSERT( ! upgrade );
Chris@16 46 BOOST_ASSERT( shared_count==0 );
Chris@16 47 }
Chris@16 48
Chris@16 49 void assert_locked() const
Chris@16 50 {
Chris@16 51 BOOST_ASSERT( exclusive );
Chris@16 52 BOOST_ASSERT( shared_count==0 );
Chris@16 53 BOOST_ASSERT( ! upgrade );
Chris@16 54 }
Chris@16 55
Chris@16 56 void assert_lock_shared () const
Chris@16 57 {
Chris@16 58 BOOST_ASSERT( ! exclusive );
Chris@16 59 BOOST_ASSERT( shared_count>0 );
Chris@16 60 //BOOST_ASSERT( (! upgrade) || (shared_count>1));
Chris@16 61 // if upgraded there are at least 2 threads sharing the mutex,
Chris@16 62 // except when unlock_upgrade_and_lock has decreased the number of readers but has not taken yet exclusive ownership.
Chris@16 63 }
Chris@16 64
Chris@16 65 void assert_lock_upgraded () const
Chris@16 66 {
Chris@16 67 BOOST_ASSERT( ! exclusive );
Chris@16 68 BOOST_ASSERT( upgrade );
Chris@16 69 BOOST_ASSERT( shared_count>0 );
Chris@16 70 }
Chris@16 71
Chris@16 72 void assert_lock_not_upgraded () const
Chris@16 73 {
Chris@16 74 BOOST_ASSERT( ! upgrade );
Chris@16 75 }
Chris@16 76
Chris@16 77 bool can_lock () const
Chris@16 78 {
Chris@16 79 return ! (shared_count || exclusive);
Chris@16 80 }
Chris@16 81
Chris@16 82 void exclusive_blocked (bool blocked)
Chris@16 83 {
Chris@16 84 exclusive_waiting_blocked = blocked;
Chris@16 85 }
Chris@16 86
Chris@16 87 void lock ()
Chris@16 88 {
Chris@16 89 exclusive = true;
Chris@16 90 }
Chris@16 91
Chris@16 92 void unlock ()
Chris@16 93 {
Chris@16 94 exclusive = false;
Chris@16 95 exclusive_waiting_blocked = false;
Chris@16 96 }
Chris@16 97
Chris@16 98 bool can_lock_shared () const
Chris@16 99 {
Chris@16 100 return ! (exclusive || exclusive_waiting_blocked);
Chris@16 101 }
Chris@16 102
Chris@16 103 bool is_last_shared () const
Chris@16 104 {
Chris@16 105 return !shared_count ;
Chris@16 106 }
Chris@16 107 unsigned get_shared_count () const
Chris@16 108 {
Chris@16 109 return shared_count ;
Chris@16 110 }
Chris@16 111 unsigned lock_shared ()
Chris@16 112 {
Chris@16 113 return ++shared_count;
Chris@16 114 }
Chris@16 115
Chris@16 116
Chris@16 117 void unlock_shared ()
Chris@16 118 {
Chris@16 119 --shared_count;
Chris@16 120 }
Chris@16 121
Chris@16 122 bool unlock_shared_downgrades()
Chris@16 123 {
Chris@16 124 if (upgrade) {
Chris@16 125 upgrade=false;
Chris@16 126 exclusive=true;
Chris@16 127 return true;
Chris@16 128 } else {
Chris@16 129 exclusive_waiting_blocked=false;
Chris@16 130 return false;
Chris@16 131 }
Chris@16 132 }
Chris@16 133
Chris@16 134 void lock_upgrade ()
Chris@16 135 {
Chris@16 136 lock_shared ();
Chris@16 137 upgrade=true;
Chris@16 138 }
Chris@16 139 bool can_lock_upgrade () const
Chris@16 140 {
Chris@16 141 return ! (exclusive || exclusive_waiting_blocked || upgrade);
Chris@16 142 }
Chris@16 143
Chris@16 144 void unlock_upgrade ()
Chris@16 145 {
Chris@16 146 upgrade=false;
Chris@16 147 unlock_shared();
Chris@16 148 }
Chris@16 149
Chris@16 150 //private:
Chris@16 151 unsigned shared_count;
Chris@16 152 bool exclusive;
Chris@16 153 bool upgrade;
Chris@16 154 bool exclusive_waiting_blocked;
Chris@16 155 };
Chris@16 156
Chris@16 157
Chris@16 158
Chris@16 159 state_data state;
Chris@16 160 boost::mutex state_change;
Chris@16 161 boost::condition_variable shared_cond;
Chris@16 162 boost::condition_variable exclusive_cond;
Chris@16 163 boost::condition_variable upgrade_cond;
Chris@16 164
Chris@16 165 void release_waiters()
Chris@16 166 {
Chris@16 167 exclusive_cond.notify_one();
Chris@16 168 shared_cond.notify_all();
Chris@16 169 }
Chris@16 170
Chris@16 171 public:
Chris@16 172 BOOST_THREAD_NO_COPYABLE(shared_mutex)
Chris@16 173
Chris@16 174 shared_mutex()
Chris@16 175 {
Chris@16 176 }
Chris@16 177
Chris@16 178 ~shared_mutex()
Chris@16 179 {
Chris@16 180 }
Chris@16 181
Chris@16 182 void lock_shared()
Chris@16 183 {
Chris@16 184 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
Chris@16 185 boost::this_thread::disable_interruption do_not_disturb;
Chris@16 186 #endif
Chris@16 187 boost::unique_lock<boost::mutex> lk(state_change);
Chris@16 188
Chris@16 189 while(!state.can_lock_shared())
Chris@16 190 {
Chris@16 191 shared_cond.wait(lk);
Chris@16 192 }
Chris@16 193 state.lock_shared();
Chris@16 194 }
Chris@16 195
Chris@16 196 bool try_lock_shared()
Chris@16 197 {
Chris@16 198 boost::unique_lock<boost::mutex> lk(state_change);
Chris@16 199 if(!state.can_lock_shared())
Chris@16 200 {
Chris@16 201 return false;
Chris@16 202 }
Chris@16 203 else
Chris@16 204 {
Chris@16 205 state.lock_shared();
Chris@16 206 return true;
Chris@16 207 }
Chris@16 208 }
Chris@16 209
Chris@16 210 #if defined BOOST_THREAD_USES_DATETIME
Chris@16 211 bool timed_lock_shared(system_time const& timeout)
Chris@16 212 {
Chris@16 213 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
Chris@16 214 boost::this_thread::disable_interruption do_not_disturb;
Chris@16 215 #endif
Chris@16 216 boost::unique_lock<boost::mutex> lk(state_change);
Chris@16 217
Chris@16 218 while(!state.can_lock_shared())
Chris@16 219 {
Chris@16 220 if(!shared_cond.timed_wait(lk,timeout))
Chris@16 221 {
Chris@16 222 return false;
Chris@16 223 }
Chris@16 224 }
Chris@16 225 state.lock_shared();
Chris@16 226 return true;
Chris@16 227 }
Chris@16 228
Chris@16 229 template<typename TimeDuration>
Chris@16 230 bool timed_lock_shared(TimeDuration const & relative_time)
Chris@16 231 {
Chris@16 232 return timed_lock_shared(get_system_time()+relative_time);
Chris@16 233 }
Chris@16 234 #endif
Chris@16 235 #ifdef BOOST_THREAD_USES_CHRONO
Chris@16 236 template <class Rep, class Period>
Chris@16 237 bool try_lock_shared_for(const chrono::duration<Rep, Period>& rel_time)
Chris@16 238 {
Chris@16 239 return try_lock_shared_until(chrono::steady_clock::now() + rel_time);
Chris@16 240 }
Chris@16 241 template <class Clock, class Duration>
Chris@16 242 bool try_lock_shared_until(const chrono::time_point<Clock, Duration>& abs_time)
Chris@16 243 {
Chris@16 244 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
Chris@16 245 boost::this_thread::disable_interruption do_not_disturb;
Chris@16 246 #endif
Chris@16 247 boost::unique_lock<boost::mutex> lk(state_change);
Chris@16 248
Chris@16 249 while(!state.can_lock_shared())
Chris@16 250 {
Chris@16 251 if(cv_status::timeout==shared_cond.wait_until(lk,abs_time))
Chris@16 252 {
Chris@16 253 return false;
Chris@16 254 }
Chris@16 255 }
Chris@16 256 state.lock_shared();
Chris@16 257 return true;
Chris@16 258 }
Chris@16 259 #endif
Chris@16 260 void unlock_shared()
Chris@16 261 {
Chris@16 262 boost::unique_lock<boost::mutex> lk(state_change);
Chris@16 263 state.assert_lock_shared();
Chris@16 264 state.unlock_shared();
Chris@16 265 if (state.get_shared_count () == 0)
Chris@16 266 {
Chris@16 267 if (state.unlock_shared_downgrades())
Chris@16 268 {
Chris@16 269 lk.unlock();
Chris@16 270 upgrade_cond.notify_one();
Chris@16 271 } else {
Chris@16 272 lk.unlock();
Chris@16 273 }
Chris@16 274 release_waiters();
Chris@16 275 }
Chris@16 276 }
Chris@16 277
Chris@16 278 void lock()
Chris@16 279 {
Chris@16 280 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
Chris@16 281 boost::this_thread::disable_interruption do_not_disturb;
Chris@16 282 #endif
Chris@16 283 boost::unique_lock<boost::mutex> lk(state_change);
Chris@16 284
Chris@16 285 while(!state.can_lock())
Chris@16 286 {
Chris@16 287 state.exclusive_blocked(true);
Chris@16 288 exclusive_cond.wait(lk);
Chris@16 289 }
Chris@16 290 state.lock();
Chris@16 291 }
Chris@16 292
Chris@16 293 #if defined BOOST_THREAD_USES_DATETIME
Chris@16 294 bool timed_lock(system_time const& timeout)
Chris@16 295 {
Chris@16 296 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
Chris@16 297 boost::this_thread::disable_interruption do_not_disturb;
Chris@16 298 #endif
Chris@16 299 boost::unique_lock<boost::mutex> lk(state_change);
Chris@16 300
Chris@16 301 while(!state.can_lock())
Chris@16 302 {
Chris@16 303 state.exclusive_blocked(true);
Chris@16 304 if(!exclusive_cond.timed_wait(lk,timeout))
Chris@16 305 {
Chris@16 306 if(!state.can_lock())
Chris@16 307 {
Chris@16 308 state.exclusive_blocked(false);
Chris@16 309 release_waiters();
Chris@16 310 return false;
Chris@16 311 }
Chris@16 312 break;
Chris@16 313 }
Chris@16 314 }
Chris@16 315 state.exclusive=true;
Chris@16 316 //state.lock();
Chris@16 317 return true;
Chris@16 318 }
Chris@16 319
Chris@16 320 template<typename TimeDuration>
Chris@16 321 bool timed_lock(TimeDuration const & relative_time)
Chris@16 322 {
Chris@16 323 return timed_lock(get_system_time()+relative_time);
Chris@16 324 }
Chris@16 325 #endif
Chris@16 326 #ifdef BOOST_THREAD_USES_CHRONO
Chris@16 327 template <class Rep, class Period>
Chris@16 328 bool try_lock_for(const chrono::duration<Rep, Period>& rel_time)
Chris@16 329 {
Chris@16 330 return try_lock_until(chrono::steady_clock::now() + rel_time);
Chris@16 331 }
Chris@16 332 template <class Clock, class Duration>
Chris@16 333 bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time)
Chris@16 334 {
Chris@16 335 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
Chris@16 336 boost::this_thread::disable_interruption do_not_disturb;
Chris@16 337 #endif
Chris@16 338 boost::unique_lock<boost::mutex> lk(state_change);
Chris@16 339
Chris@16 340 while(!state.can_lock())
Chris@16 341 {
Chris@16 342 state.exclusive_blocked(true);
Chris@16 343 if(cv_status::timeout == exclusive_cond.wait_until(lk,abs_time))
Chris@16 344 {
Chris@16 345 if(!state.can_lock())
Chris@16 346 {
Chris@16 347 state.exclusive_blocked(false);
Chris@16 348 release_waiters();
Chris@16 349 return false;
Chris@16 350 }
Chris@16 351 break;
Chris@16 352 }
Chris@16 353 }
Chris@16 354 state.exclusive=true;
Chris@16 355 //state.lock();
Chris@16 356 return true;
Chris@16 357 }
Chris@16 358 #endif
Chris@16 359
Chris@16 360 bool try_lock()
Chris@16 361 {
Chris@16 362 boost::unique_lock<boost::mutex> lk(state_change);
Chris@16 363
Chris@16 364 if(!state.can_lock())
Chris@16 365 {
Chris@16 366 return false;
Chris@16 367 }
Chris@16 368 else
Chris@16 369 {
Chris@16 370 state.lock();
Chris@16 371 return true;
Chris@16 372 }
Chris@16 373
Chris@16 374 }
Chris@16 375
Chris@16 376 void unlock()
Chris@16 377 {
Chris@16 378 boost::unique_lock<boost::mutex> lk(state_change);
Chris@16 379 state.assert_locked();
Chris@16 380 state.unlock();
Chris@16 381 state.assert_free();
Chris@16 382 release_waiters();
Chris@16 383 }
Chris@16 384
Chris@16 385 void lock_upgrade()
Chris@16 386 {
Chris@16 387 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
Chris@16 388 boost::this_thread::disable_interruption do_not_disturb;
Chris@16 389 #endif
Chris@16 390 boost::unique_lock<boost::mutex> lk(state_change);
Chris@16 391 while(!state.can_lock_upgrade())
Chris@16 392 {
Chris@16 393 shared_cond.wait(lk);
Chris@16 394 }
Chris@16 395 state.lock_upgrade();
Chris@16 396 }
Chris@16 397
Chris@16 398 #if defined BOOST_THREAD_USES_DATETIME
Chris@16 399 bool timed_lock_upgrade(system_time const& timeout)
Chris@16 400 {
Chris@16 401 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
Chris@16 402 boost::this_thread::disable_interruption do_not_disturb;
Chris@16 403 #endif
Chris@16 404 boost::unique_lock<boost::mutex> lk(state_change);
Chris@16 405 while(!state.can_lock_upgrade())
Chris@16 406 {
Chris@16 407 if(!shared_cond.timed_wait(lk,timeout))
Chris@16 408 {
Chris@16 409 if(!state.can_lock_upgrade())
Chris@16 410 {
Chris@16 411 return false;
Chris@16 412 }
Chris@16 413 break;
Chris@16 414 }
Chris@16 415 }
Chris@16 416 state.lock_upgrade();
Chris@16 417 return true;
Chris@16 418 }
Chris@16 419
Chris@16 420 template<typename TimeDuration>
Chris@16 421 bool timed_lock_upgrade(TimeDuration const & relative_time)
Chris@16 422 {
Chris@16 423 return timed_lock_upgrade(get_system_time()+relative_time);
Chris@16 424 }
Chris@16 425 #endif
Chris@16 426 #ifdef BOOST_THREAD_USES_CHRONO
Chris@16 427 template <class Rep, class Period>
Chris@16 428 bool try_lock_upgrade_for(const chrono::duration<Rep, Period>& rel_time)
Chris@16 429 {
Chris@16 430 return try_lock_upgrade_until(chrono::steady_clock::now() + rel_time);
Chris@16 431 }
Chris@16 432 template <class Clock, class Duration>
Chris@16 433 bool try_lock_upgrade_until(const chrono::time_point<Clock, Duration>& abs_time)
Chris@16 434 {
Chris@16 435 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
Chris@16 436 boost::this_thread::disable_interruption do_not_disturb;
Chris@16 437 #endif
Chris@16 438 boost::unique_lock<boost::mutex> lk(state_change);
Chris@16 439 while(!state.can_lock_upgrade())
Chris@16 440 {
Chris@16 441 if(cv_status::timeout == shared_cond.wait_until(lk,abs_time))
Chris@16 442 {
Chris@16 443 if(!state.can_lock_upgrade())
Chris@16 444 {
Chris@16 445 return false;
Chris@16 446 }
Chris@16 447 break;
Chris@16 448 }
Chris@16 449 }
Chris@16 450 state.lock_upgrade();
Chris@16 451 return true;
Chris@16 452 }
Chris@16 453 #endif
Chris@16 454 bool try_lock_upgrade()
Chris@16 455 {
Chris@16 456 boost::unique_lock<boost::mutex> lk(state_change);
Chris@16 457 if(!state.can_lock_upgrade())
Chris@16 458 {
Chris@16 459 return false;
Chris@16 460 }
Chris@16 461 else
Chris@16 462 {
Chris@16 463 state.lock_upgrade();
Chris@16 464 state.assert_lock_upgraded();
Chris@16 465 return true;
Chris@16 466 }
Chris@16 467 }
Chris@16 468
Chris@16 469 void unlock_upgrade()
Chris@16 470 {
Chris@16 471 boost::unique_lock<boost::mutex> lk(state_change);
Chris@16 472 state.assert_lock_upgraded();
Chris@16 473 state.unlock_upgrade();
Chris@16 474 state.assert_lock_not_upgraded ();
Chris@16 475 if(state.get_shared_count () == 0)
Chris@16 476 {
Chris@16 477 state.exclusive_blocked(false);
Chris@16 478 lk.unlock();
Chris@16 479 release_waiters();
Chris@16 480 } else {
Chris@16 481 lk.unlock();
Chris@16 482 shared_cond.notify_all();
Chris@16 483 }
Chris@16 484 }
Chris@16 485
Chris@16 486 // Upgrade <-> Exclusive
Chris@16 487 void unlock_upgrade_and_lock()
Chris@16 488 {
Chris@16 489 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
Chris@16 490 boost::this_thread::disable_interruption do_not_disturb;
Chris@16 491 #endif
Chris@16 492 boost::unique_lock<boost::mutex> lk(state_change);
Chris@16 493 state.assert_lock_upgraded();
Chris@16 494 // assert state.get_shared_count() >=1
Chris@16 495 while(
Chris@16 496 //! state.exclusive_waiting_blocked // Fixme: is this needed?
Chris@16 497 //&&
Chris@16 498 state.get_shared_count()!=1)
Chris@16 499 {
Chris@16 500 upgrade_cond.wait(lk);
Chris@16 501 }
Chris@16 502 state.unlock_upgrade();
Chris@16 503 state.lock();
Chris@16 504 state.assert_locked();
Chris@16 505 }
Chris@16 506
Chris@16 507 void unlock_and_lock_upgrade()
Chris@16 508 {
Chris@16 509 boost::unique_lock<boost::mutex> lk(state_change);
Chris@16 510 state.assert_locked();
Chris@16 511 state.unlock();
Chris@16 512 state.lock_upgrade();
Chris@16 513 state.assert_lock_upgraded();
Chris@16 514 release_waiters();
Chris@16 515 }
Chris@16 516
Chris@16 517 bool try_unlock_upgrade_and_lock()
Chris@16 518 {
Chris@16 519 boost::unique_lock<boost::mutex> lk(state_change);
Chris@16 520 state.assert_lock_upgraded();
Chris@16 521 if( //!state.exclusive // this should be removed once the assertion work
Chris@16 522 ! state.exclusive_waiting_blocked // Fixme: why this is needed?
Chris@16 523 //&& state.upgrade // this should be removed once the assertion work
Chris@16 524 && state.get_shared_count()==1)
Chris@16 525 {
Chris@16 526 state.unlock_upgrade();
Chris@16 527 state.lock();
Chris@16 528 state.assert_locked();
Chris@16 529 return true;
Chris@16 530 }
Chris@16 531 return false;
Chris@16 532 }
Chris@16 533 #ifdef BOOST_THREAD_USES_CHRONO
Chris@16 534 template <class Rep, class Period>
Chris@16 535 bool
Chris@16 536 try_unlock_upgrade_and_lock_for(
Chris@16 537 const chrono::duration<Rep, Period>& rel_time)
Chris@16 538 {
Chris@16 539 return try_unlock_upgrade_and_lock_until(
Chris@16 540 chrono::steady_clock::now() + rel_time);
Chris@16 541 }
Chris@16 542 template <class Clock, class Duration>
Chris@16 543 bool
Chris@16 544 try_unlock_upgrade_and_lock_until(
Chris@16 545 const chrono::time_point<Clock, Duration>& abs_time)
Chris@16 546 {
Chris@16 547 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
Chris@16 548 boost::this_thread::disable_interruption do_not_disturb;
Chris@16 549 #endif
Chris@16 550 boost::unique_lock<boost::mutex> lk(state_change);
Chris@16 551 state.assert_lock_upgraded();
Chris@16 552 if (//state.exclusive // this should be removed once the assertion work
Chris@16 553 state.exclusive_waiting_blocked // Fixme: is this needed?
Chris@16 554 //|| ! state.upgrade // this should be removed once the assertion work
Chris@16 555 || state.get_shared_count() != 1)
Chris@16 556 {
Chris@16 557 for (;;)
Chris@16 558 {
Chris@16 559 //cv_status status = shared_cond.wait_until(lk,abs_time);
Chris@16 560 cv_status status = upgrade_cond.wait_until(lk,abs_time);
Chris@16 561 if (//!state.exclusive // this should be removed once the assertion work
Chris@16 562 ! state.exclusive_waiting_blocked // Fixme: is this needed?
Chris@16 563 //&& ! state.upgrade // this should be removed once the assertion work
Chris@16 564 && state.get_shared_count() == 1)
Chris@16 565 break;
Chris@16 566 if(status == cv_status::timeout)
Chris@16 567 return false;
Chris@16 568 }
Chris@16 569 }
Chris@16 570 state.unlock_upgrade();
Chris@16 571 state.lock();
Chris@16 572 return true;
Chris@16 573 }
Chris@16 574 #endif
Chris@16 575
Chris@16 576 // Shared <-> Exclusive
Chris@16 577 void unlock_and_lock_shared()
Chris@16 578 {
Chris@16 579 boost::unique_lock<boost::mutex> lk(state_change);
Chris@16 580 state.assert_locked();
Chris@16 581 state.unlock();
Chris@16 582 state.lock_shared();
Chris@16 583 release_waiters();
Chris@16 584 }
Chris@16 585
Chris@16 586 #ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS
Chris@16 587 bool try_unlock_shared_and_lock()
Chris@16 588 {
Chris@16 589 boost::unique_lock<boost::mutex> lk(state_change);
Chris@16 590 state.assert_lock_shared();
Chris@16 591 if( //!state.exclusive // this should be removed once the assertion work
Chris@16 592 ! state.exclusive_waiting_blocked // Fixme: why this is needed?
Chris@16 593 //&& ! state.upgrade // Fixme: why this is needed if state.get_shared_count()==1?
Chris@16 594 && state.get_shared_count()==1)
Chris@16 595 {
Chris@16 596 state.unlock_shared();
Chris@16 597 state.lock();
Chris@16 598 return true;
Chris@16 599 }
Chris@16 600 return false;
Chris@16 601 }
Chris@16 602 #ifdef BOOST_THREAD_USES_CHRONO
Chris@16 603 template <class Rep, class Period>
Chris@16 604 bool
Chris@16 605 try_unlock_shared_and_lock_for(
Chris@16 606 const chrono::duration<Rep, Period>& rel_time)
Chris@16 607 {
Chris@16 608 return try_unlock_shared_and_lock_until(
Chris@16 609 chrono::steady_clock::now() + rel_time);
Chris@16 610 }
Chris@16 611 template <class Clock, class Duration>
Chris@16 612 bool
Chris@16 613 try_unlock_shared_and_lock_until(
Chris@16 614 const chrono::time_point<Clock, Duration>& abs_time)
Chris@16 615 {
Chris@16 616 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
Chris@16 617 boost::this_thread::disable_interruption do_not_disturb;
Chris@16 618 #endif
Chris@16 619 boost::unique_lock<boost::mutex> lk(state_change);
Chris@16 620 state.assert_lock_shared();
Chris@16 621 if ( // !state.exclusive // this should be removed once the assertion work
Chris@16 622 state.exclusive_waiting_blocked // Fixme: is this needed?
Chris@16 623 //|| state.upgrade // Fixme: why this is needed if state.get_shared_count()==1?
Chris@16 624 || state.get_shared_count() != 1)
Chris@16 625 {
Chris@16 626 for (;;)
Chris@16 627 {
Chris@16 628 cv_status status = shared_cond.wait_until(lk,abs_time);
Chris@16 629 if ( //! state.exclusive // this should be removed once the assertion work
Chris@16 630 ! state.exclusive_waiting_blocked // Fixme: is this needed?
Chris@16 631 //&& ! state.upgrade
Chris@16 632 && state.get_shared_count() == 1)
Chris@16 633 break;
Chris@16 634 if(status == cv_status::timeout)
Chris@16 635 return false;
Chris@16 636 }
Chris@16 637 }
Chris@16 638 state.unlock_shared();
Chris@16 639 state.lock();
Chris@16 640 state.upgrade=false; // Is this absolutely needed?
Chris@16 641 state.exclusive_waiting_blocked=false; // Is this absolutely needed?
Chris@16 642 return true;
Chris@16 643 }
Chris@16 644 #endif
Chris@16 645 #endif
Chris@16 646
Chris@16 647 // Shared <-> Upgrade
Chris@16 648 void unlock_upgrade_and_lock_shared()
Chris@16 649 {
Chris@16 650 boost::unique_lock<boost::mutex> lk(state_change);
Chris@16 651 state.assert_lock_upgraded();
Chris@16 652 //state.unlock_upgrade();
Chris@16 653 //state.lock_shared(); // less efficient
Chris@16 654 state.upgrade=false;
Chris@16 655 state.exclusive_waiting_blocked=false; // Is this absolutely needed?
Chris@16 656 release_waiters();
Chris@16 657 }
Chris@16 658
Chris@16 659 #ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS
Chris@16 660 bool try_unlock_shared_and_lock_upgrade()
Chris@16 661 {
Chris@16 662 boost::unique_lock<boost::mutex> lk(state_change);
Chris@16 663 state.assert_lock_shared();
Chris@16 664 if( //! state.exclusive // this should be removed once the assertion work
Chris@16 665 ! state.exclusive_waiting_blocked // Fixme: is this needed?
Chris@16 666 && ! state.upgrade
Chris@16 667 )
Chris@16 668 {
Chris@16 669 state.upgrade=true;
Chris@16 670 return true;
Chris@16 671 }
Chris@16 672 return false;
Chris@16 673 }
Chris@16 674 #ifdef BOOST_THREAD_USES_CHRONO
Chris@16 675 template <class Rep, class Period>
Chris@16 676 bool
Chris@16 677 try_unlock_shared_and_lock_upgrade_for(
Chris@16 678 const chrono::duration<Rep, Period>& rel_time)
Chris@16 679 {
Chris@16 680 return try_unlock_shared_and_lock_upgrade_until(
Chris@16 681 chrono::steady_clock::now() + rel_time);
Chris@16 682 }
Chris@16 683 template <class Clock, class Duration>
Chris@16 684 bool
Chris@16 685 try_unlock_shared_and_lock_upgrade_until(
Chris@16 686 const chrono::time_point<Clock, Duration>& abs_time)
Chris@16 687 {
Chris@16 688 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
Chris@16 689 boost::this_thread::disable_interruption do_not_disturb;
Chris@16 690 #endif
Chris@16 691 boost::unique_lock<boost::mutex> lk(state_change);
Chris@16 692 state.assert_lock_shared();
Chris@16 693 if( //state.exclusive // this should be removed once the assertion work
Chris@16 694 state.exclusive_waiting_blocked // Fixme: is this needed?
Chris@16 695 || state.upgrade
Chris@16 696 )
Chris@16 697 {
Chris@16 698 for (;;)
Chris@16 699 {
Chris@16 700 cv_status status = exclusive_cond.wait_until(lk,abs_time);
Chris@16 701 if( //! state.exclusive // this should be removed once the assertion work
Chris@16 702 ! state.exclusive_waiting_blocked // Fixme: is this needed?
Chris@16 703 && ! state.upgrade
Chris@16 704 )
Chris@16 705 break;
Chris@16 706 if(status == cv_status::timeout)
Chris@16 707 return false;
Chris@16 708 }
Chris@16 709 }
Chris@16 710 //state.unlock_shared();
Chris@16 711 //state.lock_upgrade(); // less efficient
Chris@16 712 state.upgrade=true;
Chris@16 713 return true;
Chris@16 714 }
Chris@16 715 #endif
Chris@16 716 #endif
Chris@16 717 };
Chris@16 718
Chris@16 719 typedef shared_mutex upgrade_mutex;
Chris@16 720 }
Chris@16 721
Chris@16 722 #include <boost/config/abi_suffix.hpp>
Chris@16 723
Chris@16 724 #endif