1 #ifndef BOOST_THREAD_WIN32_SHARED_MUTEX_HPP 2 #define BOOST_THREAD_WIN32_SHARED_MUTEX_HPP 3 4 // (C) Copyright 2006-8 Anthony Williams 5 // (C) Copyright 2011-2012 Vicente J. Botet Escriba 6 // 7 // Distributed under the Boost Software License, Version 1.0. (See 8 // accompanying file LICENSE_1_0.txt or copy at 9 // http://www.boost.org/LICENSE_1_0.txt) 10 11 #include <boost/assert.hpp> 12 #include <boost/detail/interlocked.hpp> 13 #include <boost/thread/win32/thread_primitives.hpp> 14 #include <boost/static_assert.hpp> 15 #include <limits.h> 16 #include <boost/thread/thread_time.hpp> 17 #ifdef BOOST_THREAD_USES_CHRONO 18 #include <boost/chrono/system_clocks.hpp> 19 #include <boost/chrono/ceil.hpp> 20 #endif 21 #include <boost/thread/detail/delete.hpp> 22 23 #include <boost/config/abi_prefix.hpp> 24 25 namespace boost 26 { 27 class shared_mutex 28 { 29 private: 30 struct state_data 31 { 32 unsigned shared_count:11, 33 shared_waiting:11, 34 exclusive:1, 35 upgrade:1, 36 exclusive_waiting:7, 37 exclusive_waiting_blocked:1; 38 operator ==(state_data const & lhs,state_data const & rhs)39 friend bool operator==(state_data const& lhs,state_data const& rhs) 40 { 41 return *reinterpret_cast<unsigned const*>(&lhs)==*reinterpret_cast<unsigned const*>(&rhs); 42 } 43 }; 44 45 46 template<typename T> interlocked_compare_exchange(T * target,T new_value,T comparand)47 T interlocked_compare_exchange(T* target,T new_value,T comparand) 48 { 49 BOOST_STATIC_ASSERT(sizeof(T)==sizeof(long)); 50 long const res=BOOST_INTERLOCKED_COMPARE_EXCHANGE(reinterpret_cast<long*>(target), 51 *reinterpret_cast<long*>(&new_value), 52 *reinterpret_cast<long*>(&comparand)); 53 return *reinterpret_cast<T const*>(&res); 54 } 55 56 enum 57 { 58 unlock_sem = 0, 59 exclusive_sem = 1 60 }; 61 62 state_data state; 63 detail::win32::handle semaphores[2]; 64 detail::win32::handle upgrade_sem; 65 release_waiters(state_data old_state)66 void release_waiters(state_data old_state) 67 { 68 if(old_state.exclusive_waiting) 69 { 70 BOOST_VERIFY(detail::win32::ReleaseSemaphore(semaphores[exclusive_sem],1,0)!=0); 71 } 72 73 if(old_state.shared_waiting || old_state.exclusive_waiting) 74 { 75 BOOST_VERIFY(detail::win32::ReleaseSemaphore(semaphores[unlock_sem],old_state.shared_waiting + (old_state.exclusive_waiting?1:0),0)!=0); 76 } 77 } release_shared_waiters(state_data old_state)78 void release_shared_waiters(state_data old_state) 79 { 80 if(old_state.shared_waiting || old_state.exclusive_waiting) 81 { 82 BOOST_VERIFY(detail::win32::ReleaseSemaphore(semaphores[unlock_sem],old_state.shared_waiting + (old_state.exclusive_waiting?1:0),0)!=0); 83 } 84 } 85 86 public: 87 BOOST_THREAD_NO_COPYABLE(shared_mutex) shared_mutex()88 shared_mutex() 89 { 90 semaphores[unlock_sem]=detail::win32::create_anonymous_semaphore(0,LONG_MAX); 91 semaphores[exclusive_sem]=detail::win32::create_anonymous_semaphore_nothrow(0,LONG_MAX); 92 if (!semaphores[exclusive_sem]) 93 { 94 detail::win32::release_semaphore(semaphores[unlock_sem],LONG_MAX); 95 boost::throw_exception(thread_resource_error()); 96 } 97 upgrade_sem=detail::win32::create_anonymous_semaphore_nothrow(0,LONG_MAX); 98 if (!upgrade_sem) 99 { 100 detail::win32::release_semaphore(semaphores[unlock_sem],LONG_MAX); 101 detail::win32::release_semaphore(semaphores[exclusive_sem],LONG_MAX); 102 boost::throw_exception(thread_resource_error()); 103 } 104 state_data state_={0,0,0,0,0,0}; 105 state=state_; 106 } 107 ~shared_mutex()108 ~shared_mutex() 109 { 110 detail::win32::CloseHandle(upgrade_sem); 111 detail::win32::CloseHandle(semaphores[unlock_sem]); 112 detail::win32::CloseHandle(semaphores[exclusive_sem]); 113 } 114 try_lock_shared()115 bool try_lock_shared() 116 { 117 state_data old_state=state; 118 for(;;) 119 { 120 state_data new_state=old_state; 121 if(!new_state.exclusive && !new_state.exclusive_waiting_blocked) 122 { 123 ++new_state.shared_count; 124 if(!new_state.shared_count) 125 { 126 return false; 127 } 128 } 129 130 state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); 131 if(current_state==old_state) 132 { 133 break; 134 } 135 old_state=current_state; 136 } 137 return !(old_state.exclusive| old_state.exclusive_waiting_blocked); 138 } 139 lock_shared()140 void lock_shared() 141 { 142 143 #if defined BOOST_THREAD_USES_DATETIME 144 BOOST_VERIFY(timed_lock_shared(::boost::detail::get_system_time_sentinel())); 145 #else 146 BOOST_VERIFY(try_lock_shared_until(chrono::steady_clock::now())); 147 #endif 148 } 149 150 #if defined BOOST_THREAD_USES_DATETIME 151 template<typename TimeDuration> timed_lock_shared(TimeDuration const & relative_time)152 bool timed_lock_shared(TimeDuration const & relative_time) 153 { 154 return timed_lock_shared(get_system_time()+relative_time); 155 } timed_lock_shared(boost::system_time const & wait_until)156 bool timed_lock_shared(boost::system_time const& wait_until) 157 { 158 for(;;) 159 { 160 state_data old_state=state; 161 for(;;) 162 { 163 state_data new_state=old_state; 164 if(new_state.exclusive || new_state.exclusive_waiting_blocked) 165 { 166 ++new_state.shared_waiting; 167 if(!new_state.shared_waiting) 168 { 169 boost::throw_exception(boost::lock_error()); 170 } 171 } 172 else 173 { 174 ++new_state.shared_count; 175 if(!new_state.shared_count) 176 { 177 boost::throw_exception(boost::lock_error()); 178 } 179 } 180 181 state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); 182 if(current_state==old_state) 183 { 184 break; 185 } 186 old_state=current_state; 187 } 188 189 if(!(old_state.exclusive| old_state.exclusive_waiting_blocked)) 190 { 191 return true; 192 } 193 194 unsigned long const res=detail::win32::WaitForSingleObjectEx(semaphores[unlock_sem],::boost::detail::get_milliseconds_until(wait_until), 0); 195 if(res==detail::win32::timeout) 196 { 197 for(;;) 198 { 199 state_data new_state=old_state; 200 if(new_state.exclusive || new_state.exclusive_waiting_blocked) 201 { 202 if(new_state.shared_waiting) 203 { 204 --new_state.shared_waiting; 205 } 206 } 207 else 208 { 209 ++new_state.shared_count; 210 if(!new_state.shared_count) 211 { 212 return false; 213 } 214 } 215 216 state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); 217 if(current_state==old_state) 218 { 219 break; 220 } 221 old_state=current_state; 222 } 223 224 if(!(old_state.exclusive| old_state.exclusive_waiting_blocked)) 225 { 226 return true; 227 } 228 return false; 229 } 230 231 BOOST_ASSERT(res==0); 232 } 233 } 234 #endif 235 236 #ifdef BOOST_THREAD_USES_CHRONO 237 template <class Rep, class Period> try_lock_shared_for(const chrono::duration<Rep,Period> & rel_time)238 bool try_lock_shared_for(const chrono::duration<Rep, Period>& rel_time) 239 { 240 return try_lock_shared_until(chrono::steady_clock::now() + rel_time); 241 } 242 template <class Clock, class Duration> try_lock_shared_until(const chrono::time_point<Clock,Duration> & t)243 bool try_lock_shared_until(const chrono::time_point<Clock, Duration>& t) 244 { 245 using namespace chrono; 246 system_clock::time_point s_now = system_clock::now(); 247 typename Clock::time_point c_now = Clock::now(); 248 return try_lock_shared_until(s_now + ceil<system_clock::duration>(t - c_now)); 249 } 250 template <class Duration> try_lock_shared_until(const chrono::time_point<chrono::system_clock,Duration> & t)251 bool try_lock_shared_until(const chrono::time_point<chrono::system_clock, Duration>& t) 252 { 253 using namespace chrono; 254 typedef time_point<chrono::system_clock, chrono::system_clock::duration> sys_tmpt; 255 return try_lock_shared_until(sys_tmpt(chrono::ceil<chrono::system_clock::duration>(t.time_since_epoch()))); 256 } try_lock_shared_until(const chrono::time_point<chrono::system_clock,chrono::system_clock::duration> & tp)257 bool try_lock_shared_until(const chrono::time_point<chrono::system_clock, chrono::system_clock::duration>& tp) 258 { 259 for(;;) 260 { 261 state_data old_state=state; 262 for(;;) 263 { 264 state_data new_state=old_state; 265 if(new_state.exclusive || new_state.exclusive_waiting_blocked) 266 { 267 ++new_state.shared_waiting; 268 if(!new_state.shared_waiting) 269 { 270 boost::throw_exception(boost::lock_error()); 271 } 272 } 273 else 274 { 275 ++new_state.shared_count; 276 if(!new_state.shared_count) 277 { 278 boost::throw_exception(boost::lock_error()); 279 } 280 } 281 282 state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); 283 if(current_state==old_state) 284 { 285 break; 286 } 287 old_state=current_state; 288 } 289 290 if(!(old_state.exclusive| old_state.exclusive_waiting_blocked)) 291 { 292 return true; 293 } 294 295 chrono::system_clock::time_point n = chrono::system_clock::now(); 296 unsigned long res; 297 if (tp>n) { 298 chrono::milliseconds rel_time= chrono::ceil<chrono::milliseconds>(tp-n); 299 res=detail::win32::WaitForSingleObjectEx(semaphores[unlock_sem], 300 static_cast<unsigned long>(rel_time.count()), 0); 301 } else { 302 res=detail::win32::timeout; 303 } 304 if(res==detail::win32::timeout) 305 { 306 for(;;) 307 { 308 state_data new_state=old_state; 309 if(new_state.exclusive || new_state.exclusive_waiting_blocked) 310 { 311 if(new_state.shared_waiting) 312 { 313 --new_state.shared_waiting; 314 } 315 } 316 else 317 { 318 ++new_state.shared_count; 319 if(!new_state.shared_count) 320 { 321 return false; 322 } 323 } 324 325 state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); 326 if(current_state==old_state) 327 { 328 break; 329 } 330 old_state=current_state; 331 } 332 333 if(!(old_state.exclusive| old_state.exclusive_waiting_blocked)) 334 { 335 return true; 336 } 337 return false; 338 } 339 340 BOOST_ASSERT(res==0); 341 } 342 } 343 #endif 344 unlock_shared()345 void unlock_shared() 346 { 347 state_data old_state=state; 348 for(;;) 349 { 350 state_data new_state=old_state; 351 bool const last_reader=!--new_state.shared_count; 352 353 if(last_reader) 354 { 355 if(new_state.upgrade) 356 { 357 new_state.upgrade=false; 358 new_state.exclusive=true; 359 } 360 else 361 { 362 if(new_state.exclusive_waiting) 363 { 364 --new_state.exclusive_waiting; 365 new_state.exclusive_waiting_blocked=false; 366 } 367 new_state.shared_waiting=0; 368 } 369 } 370 371 state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); 372 if(current_state==old_state) 373 { 374 if(last_reader) 375 { 376 if(old_state.upgrade) 377 { 378 BOOST_VERIFY(detail::win32::ReleaseSemaphore(upgrade_sem,1,0)!=0); 379 } 380 else 381 { 382 release_waiters(old_state); 383 } 384 } 385 break; 386 } 387 old_state=current_state; 388 } 389 } 390 lock()391 void lock() 392 { 393 394 #if defined BOOST_THREAD_USES_DATETIME 395 BOOST_VERIFY(timed_lock(::boost::detail::get_system_time_sentinel())); 396 #else 397 BOOST_VERIFY(try_lock_until(chrono::steady_clock::now())); 398 #endif 399 } 400 401 #if defined BOOST_THREAD_USES_DATETIME 402 template<typename TimeDuration> timed_lock(TimeDuration const & relative_time)403 bool timed_lock(TimeDuration const & relative_time) 404 { 405 return timed_lock(get_system_time()+relative_time); 406 } 407 #endif 408 try_lock()409 bool try_lock() 410 { 411 state_data old_state=state; 412 for(;;) 413 { 414 state_data new_state=old_state; 415 if(new_state.shared_count || new_state.exclusive) 416 { 417 return false; 418 } 419 else 420 { 421 new_state.exclusive=true; 422 } 423 424 state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); 425 if(current_state==old_state) 426 { 427 break; 428 } 429 old_state=current_state; 430 } 431 return true; 432 } 433 434 435 #if defined BOOST_THREAD_USES_DATETIME timed_lock(boost::system_time const & wait_until)436 bool timed_lock(boost::system_time const& wait_until) 437 { 438 for(;;) 439 { 440 state_data old_state=state; 441 442 for(;;) 443 { 444 state_data new_state=old_state; 445 if(new_state.shared_count || new_state.exclusive) 446 { 447 ++new_state.exclusive_waiting; 448 if(!new_state.exclusive_waiting) 449 { 450 boost::throw_exception(boost::lock_error()); 451 } 452 453 new_state.exclusive_waiting_blocked=true; 454 } 455 else 456 { 457 new_state.exclusive=true; 458 } 459 460 state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); 461 if(current_state==old_state) 462 { 463 break; 464 } 465 old_state=current_state; 466 } 467 468 if(!old_state.shared_count && !old_state.exclusive) 469 { 470 return true; 471 } 472 #ifndef UNDER_CE 473 const bool wait_all = true; 474 #else 475 const bool wait_all = false; 476 #endif 477 unsigned long const wait_res=detail::win32::WaitForMultipleObjectsEx(2,semaphores,wait_all,::boost::detail::get_milliseconds_until(wait_until), 0); 478 if(wait_res==detail::win32::timeout) 479 { 480 for(;;) 481 { 482 bool must_notify = false; 483 state_data new_state=old_state; 484 if(new_state.shared_count || new_state.exclusive) 485 { 486 if(new_state.exclusive_waiting) 487 { 488 if(!--new_state.exclusive_waiting) 489 { 490 new_state.exclusive_waiting_blocked=false; 491 must_notify = true; 492 } 493 } 494 } 495 else 496 { 497 new_state.exclusive=true; 498 } 499 500 state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); 501 if (must_notify) 502 { 503 BOOST_VERIFY(detail::win32::ReleaseSemaphore(semaphores[unlock_sem],1,0)!=0); 504 } 505 506 if(current_state==old_state) 507 { 508 break; 509 } 510 old_state=current_state; 511 } 512 if(!old_state.shared_count && !old_state.exclusive) 513 { 514 return true; 515 } 516 return false; 517 } 518 BOOST_ASSERT(wait_res<2); 519 } 520 } 521 #endif 522 #ifdef BOOST_THREAD_USES_CHRONO 523 template <class Rep, class Period> try_lock_for(const chrono::duration<Rep,Period> & rel_time)524 bool try_lock_for(const chrono::duration<Rep, Period>& rel_time) 525 { 526 return try_lock_until(chrono::steady_clock::now() + rel_time); 527 } 528 template <class Clock, class Duration> try_lock_until(const chrono::time_point<Clock,Duration> & t)529 bool try_lock_until(const chrono::time_point<Clock, Duration>& t) 530 { 531 using namespace chrono; 532 system_clock::time_point s_now = system_clock::now(); 533 typename Clock::time_point c_now = Clock::now(); 534 return try_lock_until(s_now + ceil<system_clock::duration>(t - c_now)); 535 } 536 template <class Duration> try_lock_until(const chrono::time_point<chrono::system_clock,Duration> & t)537 bool try_lock_until(const chrono::time_point<chrono::system_clock, Duration>& t) 538 { 539 using namespace chrono; 540 typedef time_point<chrono::system_clock, chrono::system_clock::duration> sys_tmpt; 541 return try_lock_until(sys_tmpt(chrono::ceil<chrono::system_clock::duration>(t.time_since_epoch()))); 542 } try_lock_until(const chrono::time_point<chrono::system_clock,chrono::system_clock::duration> & tp)543 bool try_lock_until(const chrono::time_point<chrono::system_clock, chrono::system_clock::duration>& tp) 544 { 545 for(;;) 546 { 547 state_data old_state=state; 548 549 for(;;) 550 { 551 state_data new_state=old_state; 552 if(new_state.shared_count || new_state.exclusive) 553 { 554 ++new_state.exclusive_waiting; 555 if(!new_state.exclusive_waiting) 556 { 557 boost::throw_exception(boost::lock_error()); 558 } 559 560 new_state.exclusive_waiting_blocked=true; 561 } 562 else 563 { 564 new_state.exclusive=true; 565 } 566 567 state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); 568 if(current_state==old_state) 569 { 570 break; 571 } 572 old_state=current_state; 573 } 574 575 if(!old_state.shared_count && !old_state.exclusive) 576 { 577 return true; 578 } 579 #ifndef UNDER_CE 580 const bool wait_all = true; 581 #else 582 const bool wait_all = false; 583 #endif 584 585 chrono::system_clock::time_point n = chrono::system_clock::now(); 586 unsigned long wait_res; 587 if (tp>n) { 588 chrono::milliseconds rel_time= chrono::ceil<chrono::milliseconds>(tp-chrono::system_clock::now()); 589 wait_res=detail::win32::WaitForMultipleObjectsEx(2,semaphores,wait_all, 590 static_cast<unsigned long>(rel_time.count()), 0); 591 } else { 592 wait_res=detail::win32::timeout; 593 } 594 if(wait_res==detail::win32::timeout) 595 { 596 for(;;) 597 { 598 bool must_notify = false; 599 state_data new_state=old_state; 600 if(new_state.shared_count || new_state.exclusive) 601 { 602 if(new_state.exclusive_waiting) 603 { 604 if(!--new_state.exclusive_waiting) 605 { 606 new_state.exclusive_waiting_blocked=false; 607 must_notify = true; 608 } 609 } 610 } 611 else 612 { 613 new_state.exclusive=true; 614 } 615 616 state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); 617 if (must_notify) 618 { 619 BOOST_VERIFY(detail::win32::ReleaseSemaphore(semaphores[unlock_sem],1,0)!=0); 620 } 621 if(current_state==old_state) 622 { 623 break; 624 } 625 old_state=current_state; 626 } 627 if(!old_state.shared_count && !old_state.exclusive) 628 { 629 return true; 630 } 631 return false; 632 } 633 BOOST_ASSERT(wait_res<2); 634 } 635 } 636 #endif 637 unlock()638 void unlock() 639 { 640 state_data old_state=state; 641 for(;;) 642 { 643 state_data new_state=old_state; 644 new_state.exclusive=false; 645 if(new_state.exclusive_waiting) 646 { 647 --new_state.exclusive_waiting; 648 new_state.exclusive_waiting_blocked=false; 649 } 650 new_state.shared_waiting=0; 651 652 state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); 653 if(current_state==old_state) 654 { 655 break; 656 } 657 old_state=current_state; 658 } 659 release_waiters(old_state); 660 } 661 lock_upgrade()662 void lock_upgrade() 663 { 664 for(;;) 665 { 666 state_data old_state=state; 667 for(;;) 668 { 669 state_data new_state=old_state; 670 if(new_state.exclusive || new_state.exclusive_waiting_blocked || new_state.upgrade) 671 { 672 ++new_state.shared_waiting; 673 if(!new_state.shared_waiting) 674 { 675 boost::throw_exception(boost::lock_error()); 676 } 677 } 678 else 679 { 680 ++new_state.shared_count; 681 if(!new_state.shared_count) 682 { 683 boost::throw_exception(boost::lock_error()); 684 } 685 new_state.upgrade=true; 686 } 687 688 state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); 689 if(current_state==old_state) 690 { 691 break; 692 } 693 old_state=current_state; 694 } 695 696 if(!(old_state.exclusive|| old_state.exclusive_waiting_blocked|| old_state.upgrade)) 697 { 698 return; 699 } 700 701 BOOST_VERIFY(!detail::win32::WaitForSingleObjectEx(semaphores[unlock_sem],detail::win32::infinite, 0)); 702 } 703 } 704 try_lock_upgrade()705 bool try_lock_upgrade() 706 { 707 state_data old_state=state; 708 for(;;) 709 { 710 state_data new_state=old_state; 711 if(new_state.exclusive || new_state.exclusive_waiting_blocked || new_state.upgrade) 712 { 713 return false; 714 } 715 else 716 { 717 ++new_state.shared_count; 718 if(!new_state.shared_count) 719 { 720 return false; 721 } 722 new_state.upgrade=true; 723 } 724 725 state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); 726 if(current_state==old_state) 727 { 728 break; 729 } 730 old_state=current_state; 731 } 732 return true; 733 } 734 unlock_upgrade()735 void unlock_upgrade() 736 { 737 state_data old_state=state; 738 for(;;) 739 { 740 state_data new_state=old_state; 741 new_state.upgrade=false; 742 bool const last_reader=!--new_state.shared_count; 743 744 new_state.shared_waiting=0; 745 if(last_reader) 746 { 747 if(new_state.exclusive_waiting) 748 { 749 --new_state.exclusive_waiting; 750 new_state.exclusive_waiting_blocked=false; 751 } 752 } 753 754 state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); 755 if(current_state==old_state) 756 { 757 if(last_reader) 758 { 759 release_waiters(old_state); 760 } 761 else { 762 release_shared_waiters(old_state); 763 } 764 // #7720 765 //else { 766 // release_waiters(old_state); 767 //} 768 break; 769 } 770 old_state=current_state; 771 } 772 } 773 unlock_upgrade_and_lock()774 void unlock_upgrade_and_lock() 775 { 776 state_data old_state=state; 777 for(;;) 778 { 779 state_data new_state=old_state; 780 bool const last_reader=!--new_state.shared_count; 781 782 if(last_reader) 783 { 784 new_state.upgrade=false; 785 new_state.exclusive=true; 786 } 787 788 state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); 789 if(current_state==old_state) 790 { 791 if(!last_reader) 792 { 793 BOOST_VERIFY(!detail::win32::WaitForSingleObjectEx(upgrade_sem,detail::win32::infinite, 0)); 794 } 795 break; 796 } 797 old_state=current_state; 798 } 799 } 800 unlock_and_lock_upgrade()801 void unlock_and_lock_upgrade() 802 { 803 state_data old_state=state; 804 for(;;) 805 { 806 state_data new_state=old_state; 807 new_state.exclusive=false; 808 new_state.upgrade=true; 809 ++new_state.shared_count; 810 if(new_state.exclusive_waiting) 811 { 812 --new_state.exclusive_waiting; 813 new_state.exclusive_waiting_blocked=false; 814 } 815 new_state.shared_waiting=0; 816 817 state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); 818 if(current_state==old_state) 819 { 820 break; 821 } 822 old_state=current_state; 823 } 824 release_waiters(old_state); 825 } 826 // bool try_unlock_upgrade_and_lock() 827 // { 828 // return false; 829 // } 830 //#ifdef BOOST_THREAD_USES_CHRONO 831 // template <class Rep, class Period> 832 // bool 833 // try_unlock_upgrade_and_lock_for( 834 // const chrono::duration<Rep, Period>& rel_time) 835 // { 836 // return try_unlock_upgrade_and_lock_until( 837 // chrono::steady_clock::now() + rel_time); 838 // } 839 // template <class Clock, class Duration> 840 // bool 841 // try_unlock_upgrade_and_lock_until( 842 // const chrono::time_point<Clock, Duration>& abs_time) 843 // { 844 // return false; 845 // } 846 //#endif 847 unlock_and_lock_shared()848 void unlock_and_lock_shared() 849 { 850 state_data old_state=state; 851 for(;;) 852 { 853 state_data new_state=old_state; 854 new_state.exclusive=false; 855 ++new_state.shared_count; 856 if(new_state.exclusive_waiting) 857 { 858 --new_state.exclusive_waiting; 859 new_state.exclusive_waiting_blocked=false; 860 } 861 new_state.shared_waiting=0; 862 863 state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); 864 if(current_state==old_state) 865 { 866 break; 867 } 868 old_state=current_state; 869 } 870 release_waiters(old_state); 871 } unlock_upgrade_and_lock_shared()872 void unlock_upgrade_and_lock_shared() 873 { 874 state_data old_state=state; 875 for(;;) 876 { 877 state_data new_state=old_state; 878 new_state.upgrade=false; 879 if(new_state.exclusive_waiting) 880 { 881 --new_state.exclusive_waiting; 882 new_state.exclusive_waiting_blocked=false; 883 } 884 new_state.shared_waiting=0; 885 886 state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); 887 if(current_state==old_state) 888 { 889 break; 890 } 891 old_state=current_state; 892 } 893 release_waiters(old_state); 894 } 895 896 }; 897 typedef shared_mutex upgrade_mutex; 898 899 } 900 901 #include <boost/config/abi_suffix.hpp> 902 903 #endif 904