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