Warning, file /include/boost/thread/win32/shared_mutex.hpp was not indexed
or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 #ifndef BOOST_THREAD_WIN32_SHARED_MUTEX_HPP
0002 #define BOOST_THREAD_WIN32_SHARED_MUTEX_HPP
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <cstring>
0012 #include <boost/assert.hpp>
0013 #include <boost/detail/interlocked.hpp>
0014 #include <boost/thread/win32/thread_primitives.hpp>
0015 #include <boost/static_assert.hpp>
0016 #include <limits.h>
0017 #include <boost/thread/thread_time.hpp>
0018 #ifdef BOOST_THREAD_USES_CHRONO
0019 #include <boost/chrono/system_clocks.hpp>
0020 #include <boost/chrono/ceil.hpp>
0021 #endif
0022 #include <boost/thread/detail/delete.hpp>
0023 #include <boost/thread/detail/platform_time.hpp>
0024
0025 #include <boost/config/abi_prefix.hpp>
0026
0027 namespace boost
0028 {
0029 class shared_mutex
0030 {
0031 private:
0032 struct state_data
0033 {
0034 unsigned long shared_count:11,
0035 shared_waiting:11,
0036 exclusive:1,
0037 upgrade:1,
0038 exclusive_waiting:7,
0039 exclusive_waiting_blocked:1;
0040
0041 friend bool operator==(state_data const& lhs,state_data const& rhs)
0042 {
0043 return std::memcmp(&lhs, &rhs, sizeof(lhs)) == 0;
0044 }
0045 };
0046
0047 static state_data interlocked_compare_exchange(state_data* target, state_data new_value, state_data comparand)
0048 {
0049 BOOST_STATIC_ASSERT(sizeof(state_data) == sizeof(long));
0050 long new_val, comp;
0051 std::memcpy(&new_val, &new_value, sizeof(new_value));
0052 std::memcpy(&comp, &comparand, sizeof(comparand));
0053 long const res=BOOST_INTERLOCKED_COMPARE_EXCHANGE(reinterpret_cast<long*>(target),
0054 new_val,
0055 comp);
0056 state_data result;
0057 std::memcpy(&result, &res, sizeof(result));
0058 return result;
0059 }
0060
0061 enum
0062 {
0063 unlock_sem = 0,
0064 exclusive_sem = 1
0065 };
0066
0067 state_data state;
0068 detail::win32::handle semaphores[2];
0069 detail::win32::handle upgrade_sem;
0070
0071 void release_waiters(state_data old_state)
0072 {
0073 if(old_state.exclusive_waiting)
0074 {
0075 BOOST_VERIFY(winapi::ReleaseSemaphore(semaphores[exclusive_sem],1,0)!=0);
0076 }
0077
0078 if(old_state.shared_waiting || old_state.exclusive_waiting)
0079 {
0080 BOOST_VERIFY(winapi::ReleaseSemaphore(semaphores[unlock_sem],old_state.shared_waiting + (old_state.exclusive_waiting?1:0),0)!=0);
0081 }
0082 }
0083 void release_shared_waiters(state_data old_state)
0084 {
0085 if(old_state.shared_waiting || old_state.exclusive_waiting)
0086 {
0087 BOOST_VERIFY(winapi::ReleaseSemaphore(semaphores[unlock_sem],old_state.shared_waiting + (old_state.exclusive_waiting?1:0),0)!=0);
0088 }
0089 }
0090
0091 public:
0092 BOOST_THREAD_NO_COPYABLE(shared_mutex)
0093 shared_mutex()
0094 {
0095 semaphores[unlock_sem]=detail::win32::create_anonymous_semaphore(0,LONG_MAX);
0096 semaphores[exclusive_sem]=detail::win32::create_anonymous_semaphore_nothrow(0,LONG_MAX);
0097 if (!semaphores[exclusive_sem])
0098 {
0099 detail::win32::release_semaphore(semaphores[unlock_sem],LONG_MAX);
0100 boost::throw_exception(thread_resource_error());
0101 }
0102 upgrade_sem=detail::win32::create_anonymous_semaphore_nothrow(0,LONG_MAX);
0103 if (!upgrade_sem)
0104 {
0105 detail::win32::release_semaphore(semaphores[unlock_sem],LONG_MAX);
0106 detail::win32::release_semaphore(semaphores[exclusive_sem],LONG_MAX);
0107 boost::throw_exception(thread_resource_error());
0108 }
0109 state_data state_={0,0,0,0,0,0};
0110 state=state_;
0111 }
0112
0113 ~shared_mutex()
0114 {
0115 winapi::CloseHandle(upgrade_sem);
0116 winapi::CloseHandle(semaphores[unlock_sem]);
0117 winapi::CloseHandle(semaphores[exclusive_sem]);
0118 }
0119
0120 bool try_lock_shared()
0121 {
0122 state_data old_state=state;
0123 for(;;)
0124 {
0125 state_data new_state=old_state;
0126 if(!new_state.exclusive && !new_state.exclusive_waiting_blocked)
0127 {
0128 ++new_state.shared_count;
0129 if(!new_state.shared_count)
0130 {
0131 return false;
0132 }
0133 }
0134
0135 state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
0136 if(current_state==old_state)
0137 {
0138 break;
0139 }
0140 old_state=current_state;
0141 }
0142 return !(old_state.exclusive| old_state.exclusive_waiting_blocked);
0143 }
0144
0145 void lock_shared()
0146 {
0147 for(;;)
0148 {
0149 state_data old_state=state;
0150 for(;;)
0151 {
0152 state_data new_state=old_state;
0153 if(new_state.exclusive || new_state.exclusive_waiting_blocked)
0154 {
0155 ++new_state.shared_waiting;
0156 if(!new_state.shared_waiting)
0157 {
0158 boost::throw_exception(boost::lock_error());
0159 }
0160 }
0161 else
0162 {
0163 ++new_state.shared_count;
0164 if(!new_state.shared_count)
0165 {
0166 boost::throw_exception(boost::lock_error());
0167 }
0168 }
0169
0170 state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
0171 if(current_state==old_state)
0172 {
0173 break;
0174 }
0175 old_state=current_state;
0176 }
0177
0178 if(!(old_state.exclusive| old_state.exclusive_waiting_blocked))
0179 {
0180 return;
0181 }
0182
0183 BOOST_VERIFY(winapi::WaitForSingleObjectEx(semaphores[unlock_sem],::boost::detail::win32::infinite,0)==0);
0184 }
0185 }
0186
0187 private:
0188 unsigned long getMs(detail::platform_duration const& d)
0189 {
0190 return static_cast<unsigned long>(d.getMs());
0191 }
0192
0193 template <typename Duration>
0194 unsigned long getMs(Duration const& d)
0195 {
0196 return static_cast<unsigned long>(chrono::ceil<chrono::milliseconds>(d).count());
0197 }
0198
0199 template <typename Clock, typename Timepoint, typename Duration>
0200 bool do_lock_shared_until(Timepoint const& t, Duration const& max)
0201 {
0202 for(;;)
0203 {
0204 state_data old_state=state;
0205 for(;;)
0206 {
0207 state_data new_state=old_state;
0208 if(new_state.exclusive || new_state.exclusive_waiting_blocked)
0209 {
0210 ++new_state.shared_waiting;
0211 if(!new_state.shared_waiting)
0212 {
0213 boost::throw_exception(boost::lock_error());
0214 }
0215 }
0216 else
0217 {
0218 ++new_state.shared_count;
0219 if(!new_state.shared_count)
0220 {
0221 boost::throw_exception(boost::lock_error());
0222 }
0223 }
0224
0225 state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
0226 if(current_state==old_state)
0227 {
0228 break;
0229 }
0230 old_state=current_state;
0231 }
0232
0233 if(!(old_state.exclusive| old_state.exclusive_waiting_blocked))
0234 {
0235 return true;
0236 }
0237
0238
0239
0240
0241
0242 unsigned long res=0;
0243 for(;;)
0244 {
0245 Duration d(t - Clock::now());
0246 if(d <= Duration::zero())
0247 {
0248 res=detail::win32::timeout;
0249 break;
0250 }
0251 if(max != Duration::zero())
0252 {
0253 d = (std::min)(d, max);
0254 }
0255 res=winapi::WaitForSingleObjectEx(semaphores[unlock_sem],getMs(d),0);
0256 if(res!=detail::win32::timeout)
0257 {
0258 break;
0259 }
0260 }
0261
0262 if(res==detail::win32::timeout)
0263 {
0264 for(;;)
0265 {
0266 state_data new_state=old_state;
0267 if(new_state.exclusive || new_state.exclusive_waiting_blocked)
0268 {
0269 if(new_state.shared_waiting)
0270 {
0271 --new_state.shared_waiting;
0272 }
0273 }
0274 else
0275 {
0276 ++new_state.shared_count;
0277 if(!new_state.shared_count)
0278 {
0279 return false;
0280 }
0281 }
0282
0283 state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
0284 if(current_state==old_state)
0285 {
0286 break;
0287 }
0288 old_state=current_state;
0289 }
0290
0291 if(!(old_state.exclusive| old_state.exclusive_waiting_blocked))
0292 {
0293 return true;
0294 }
0295 return false;
0296 }
0297
0298 BOOST_ASSERT(res==0);
0299 }
0300 }
0301 public:
0302
0303 #if defined BOOST_THREAD_USES_DATETIME
0304 template<typename TimeDuration>
0305 bool timed_lock_shared(TimeDuration const & relative_time)
0306 {
0307 const detail::mono_platform_timepoint t(detail::mono_platform_clock::now() + detail::platform_duration(relative_time));
0308
0309 return do_lock_shared_until<detail::mono_platform_clock>(t, detail::platform_duration::zero());
0310 }
0311 bool timed_lock_shared(boost::system_time const& wait_until)
0312 {
0313 const detail::real_platform_timepoint t(wait_until);
0314 return do_lock_shared_until<detail::real_platform_clock>(t, detail::platform_milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS));
0315 }
0316 #endif
0317
0318 #ifdef BOOST_THREAD_USES_CHRONO
0319 template <class Rep, class Period>
0320 bool try_lock_shared_for(const chrono::duration<Rep, Period>& rel_time)
0321 {
0322 const chrono::steady_clock::time_point t(chrono::steady_clock::now() + rel_time);
0323 typedef typename chrono::duration<Rep, Period> Duration;
0324 typedef typename common_type<Duration, typename chrono::steady_clock::duration>::type common_duration;
0325
0326 return do_lock_shared_until<chrono::steady_clock>(t, common_duration::zero());
0327 }
0328 template <class Duration>
0329 bool try_lock_shared_until(const chrono::time_point<chrono::steady_clock, Duration>& t)
0330 {
0331 typedef typename common_type<Duration, typename chrono::steady_clock::duration>::type common_duration;
0332
0333 return do_lock_shared_until<chrono::steady_clock>(t, common_duration::zero());
0334 }
0335 template <class Clock, class Duration>
0336 bool try_lock_shared_until(const chrono::time_point<Clock, Duration>& t)
0337 {
0338 typedef typename common_type<Duration, typename Clock::duration>::type common_duration;
0339 return do_lock_shared_until<Clock>(t, common_duration(chrono::milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS)));
0340 }
0341 #endif
0342
0343 void unlock_shared()
0344 {
0345 state_data old_state=state;
0346 for(;;)
0347 {
0348 state_data new_state=old_state;
0349 bool const last_reader=!--new_state.shared_count;
0350
0351 if(last_reader)
0352 {
0353 if(new_state.upgrade)
0354 {
0355 new_state.upgrade=false;
0356 new_state.exclusive=true;
0357 }
0358 else
0359 {
0360 if(new_state.exclusive_waiting)
0361 {
0362 --new_state.exclusive_waiting;
0363 new_state.exclusive_waiting_blocked=false;
0364 }
0365 new_state.shared_waiting=0;
0366 }
0367 }
0368
0369 state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
0370 if(current_state==old_state)
0371 {
0372 if(last_reader)
0373 {
0374 if(old_state.upgrade)
0375 {
0376 BOOST_VERIFY(winapi::ReleaseSemaphore(upgrade_sem,1,0)!=0);
0377 }
0378 else
0379 {
0380 release_waiters(old_state);
0381 }
0382 }
0383 break;
0384 }
0385 old_state=current_state;
0386 }
0387 }
0388
0389 bool try_lock()
0390 {
0391 state_data old_state=state;
0392 for(;;)
0393 {
0394 state_data new_state=old_state;
0395 if(new_state.shared_count || new_state.exclusive)
0396 {
0397 return false;
0398 }
0399 else
0400 {
0401 new_state.exclusive=true;
0402 }
0403
0404 state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
0405 if(current_state==old_state)
0406 {
0407 break;
0408 }
0409 old_state=current_state;
0410 }
0411 return true;
0412 }
0413
0414 void lock()
0415 {
0416 for(;;)
0417 {
0418 state_data old_state=state;
0419 for(;;)
0420 {
0421 state_data new_state=old_state;
0422 if(new_state.shared_count || new_state.exclusive)
0423 {
0424 ++new_state.exclusive_waiting;
0425 if(!new_state.exclusive_waiting)
0426 {
0427 boost::throw_exception(boost::lock_error());
0428 }
0429
0430 new_state.exclusive_waiting_blocked=true;
0431 }
0432 else
0433 {
0434 new_state.exclusive=true;
0435 }
0436
0437 state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
0438 if(current_state==old_state)
0439 {
0440 break;
0441 }
0442 old_state=current_state;
0443 }
0444
0445 if(!old_state.shared_count && !old_state.exclusive)
0446 {
0447 return;
0448 }
0449
0450 #ifndef UNDER_CE
0451 const bool wait_all = true;
0452 #else
0453 const bool wait_all = false;
0454 #endif
0455 BOOST_VERIFY(winapi::WaitForMultipleObjectsEx(2,semaphores,wait_all,::boost::detail::win32::infinite,0)<2);
0456 }
0457 }
0458
0459 private:
0460 template <typename Clock, typename Timepoint, typename Duration>
0461 bool do_lock_until(Timepoint const& t, Duration const& max)
0462 {
0463 for(;;)
0464 {
0465 state_data old_state=state;
0466 for(;;)
0467 {
0468 state_data new_state=old_state;
0469 if(new_state.shared_count || new_state.exclusive)
0470 {
0471 ++new_state.exclusive_waiting;
0472 if(!new_state.exclusive_waiting)
0473 {
0474 boost::throw_exception(boost::lock_error());
0475 }
0476
0477 new_state.exclusive_waiting_blocked=true;
0478 }
0479 else
0480 {
0481 new_state.exclusive=true;
0482 }
0483
0484 state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
0485 if(current_state==old_state)
0486 {
0487 break;
0488 }
0489 old_state=current_state;
0490 }
0491
0492 if(!old_state.shared_count && !old_state.exclusive)
0493 {
0494 return true;
0495 }
0496
0497
0498
0499
0500
0501 unsigned long wait_res=0;
0502 for(;;)
0503 {
0504 Duration d(t - Clock::now());
0505 if(d <= Duration::zero())
0506 {
0507 wait_res=detail::win32::timeout;
0508 break;
0509 }
0510 if(max != Duration::zero())
0511 {
0512 d = (std::min)(d, max);
0513 }
0514 #ifndef UNDER_CE
0515 wait_res=winapi::WaitForMultipleObjectsEx(2,semaphores,true,getMs(d),0);
0516 #else
0517 wait_res=winapi::WaitForMultipleObjectsEx(2,semaphores,false,getMs(d),0);
0518 #endif
0519
0520
0521 if(wait_res!=detail::win32::timeout)
0522 {
0523 break;
0524 }
0525 }
0526
0527 if(wait_res==detail::win32::timeout)
0528 {
0529 for(;;)
0530 {
0531 bool must_notify = false;
0532 state_data new_state=old_state;
0533 if(new_state.shared_count || new_state.exclusive)
0534 {
0535 if(new_state.exclusive_waiting)
0536 {
0537 if(!--new_state.exclusive_waiting)
0538 {
0539 new_state.exclusive_waiting_blocked=false;
0540 must_notify = true;
0541 }
0542 }
0543 }
0544 else
0545 {
0546 new_state.exclusive=true;
0547 }
0548
0549 state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
0550 if (must_notify)
0551 {
0552 BOOST_VERIFY(winapi::ReleaseSemaphore(semaphores[unlock_sem],1,0)!=0);
0553 }
0554
0555 if(current_state==old_state)
0556 {
0557 break;
0558 }
0559 old_state=current_state;
0560 }
0561 if(!old_state.shared_count && !old_state.exclusive)
0562 {
0563 return true;
0564 }
0565 return false;
0566 }
0567
0568 BOOST_ASSERT(wait_res<2);
0569 }
0570 }
0571 public:
0572
0573 #if defined BOOST_THREAD_USES_DATETIME
0574 bool timed_lock(boost::system_time const& wait_until)
0575 {
0576 const detail::real_platform_timepoint t(wait_until);
0577 return do_lock_until<detail::real_platform_clock>(t, detail::platform_milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS));
0578 }
0579 template<typename TimeDuration>
0580 bool timed_lock(TimeDuration const & relative_time)
0581 {
0582 const detail::mono_platform_timepoint t(detail::mono_platform_clock::now() + detail::platform_duration(relative_time));
0583
0584 return do_lock_until<detail::mono_platform_clock>(t, detail::platform_duration::zero());
0585 }
0586 #endif
0587 #ifdef BOOST_THREAD_USES_CHRONO
0588 template <class Rep, class Period>
0589 bool try_lock_for(const chrono::duration<Rep, Period>& rel_time)
0590 {
0591 const chrono::steady_clock::time_point t(chrono::steady_clock::now() + rel_time);
0592 typedef typename chrono::duration<Rep, Period> Duration;
0593 typedef typename common_type<Duration, typename chrono::steady_clock::duration>::type common_duration;
0594
0595 return do_lock_until<chrono::steady_clock>(t, common_duration::zero());
0596 }
0597 template <class Duration>
0598 bool try_lock_until(const chrono::time_point<chrono::steady_clock, Duration>& t)
0599 {
0600 typedef typename common_type<Duration, typename chrono::steady_clock::duration>::type common_duration;
0601
0602 return do_lock_until<chrono::steady_clock>(t, common_duration::zero());
0603 }
0604 template <class Clock, class Duration>
0605 bool try_lock_until(const chrono::time_point<Clock, Duration>& t)
0606 {
0607 typedef typename common_type<Duration, typename Clock::duration>::type common_duration;
0608 return do_lock_until<Clock>(t, common_duration(chrono::milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS)));
0609 }
0610 #endif
0611
0612 void unlock()
0613 {
0614 state_data old_state=state;
0615 for(;;)
0616 {
0617 state_data new_state=old_state;
0618 new_state.exclusive=false;
0619 if(new_state.exclusive_waiting)
0620 {
0621 --new_state.exclusive_waiting;
0622 new_state.exclusive_waiting_blocked=false;
0623 }
0624 new_state.shared_waiting=0;
0625
0626 state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
0627 if(current_state==old_state)
0628 {
0629 break;
0630 }
0631 old_state=current_state;
0632 }
0633 release_waiters(old_state);
0634 }
0635
0636 void lock_upgrade()
0637 {
0638 for(;;)
0639 {
0640 state_data old_state=state;
0641 for(;;)
0642 {
0643 state_data new_state=old_state;
0644 if(new_state.exclusive || new_state.exclusive_waiting_blocked || new_state.upgrade)
0645 {
0646 ++new_state.shared_waiting;
0647 if(!new_state.shared_waiting)
0648 {
0649 boost::throw_exception(boost::lock_error());
0650 }
0651 }
0652 else
0653 {
0654 ++new_state.shared_count;
0655 if(!new_state.shared_count)
0656 {
0657 boost::throw_exception(boost::lock_error());
0658 }
0659 new_state.upgrade=true;
0660 }
0661
0662 state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
0663 if(current_state==old_state)
0664 {
0665 break;
0666 }
0667 old_state=current_state;
0668 }
0669
0670 if(!(old_state.exclusive|| old_state.exclusive_waiting_blocked|| old_state.upgrade))
0671 {
0672 return;
0673 }
0674
0675 BOOST_VERIFY(winapi::WaitForSingleObjectEx(semaphores[unlock_sem],winapi::infinite,0)==0);
0676 }
0677 }
0678
0679 bool try_lock_upgrade()
0680 {
0681 state_data old_state=state;
0682 for(;;)
0683 {
0684 state_data new_state=old_state;
0685 if(new_state.exclusive || new_state.exclusive_waiting_blocked || new_state.upgrade)
0686 {
0687 return false;
0688 }
0689 else
0690 {
0691 ++new_state.shared_count;
0692 if(!new_state.shared_count)
0693 {
0694 return false;
0695 }
0696 new_state.upgrade=true;
0697 }
0698
0699 state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
0700 if(current_state==old_state)
0701 {
0702 break;
0703 }
0704 old_state=current_state;
0705 }
0706 return true;
0707 }
0708
0709 void unlock_upgrade()
0710 {
0711 state_data old_state=state;
0712 for(;;)
0713 {
0714 state_data new_state=old_state;
0715 new_state.upgrade=false;
0716 bool const last_reader=!--new_state.shared_count;
0717
0718 new_state.shared_waiting=0;
0719 if(last_reader)
0720 {
0721 if(new_state.exclusive_waiting)
0722 {
0723 --new_state.exclusive_waiting;
0724 new_state.exclusive_waiting_blocked=false;
0725 }
0726 }
0727
0728 state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
0729 if(current_state==old_state)
0730 {
0731 if(last_reader)
0732 {
0733 release_waiters(old_state);
0734 }
0735 else {
0736 release_shared_waiters(old_state);
0737 }
0738
0739
0740
0741
0742 break;
0743 }
0744 old_state=current_state;
0745 }
0746 }
0747
0748 void unlock_upgrade_and_lock()
0749 {
0750 state_data old_state=state;
0751 for(;;)
0752 {
0753 state_data new_state=old_state;
0754 bool const last_reader=!--new_state.shared_count;
0755
0756 if(last_reader)
0757 {
0758 new_state.upgrade=false;
0759 new_state.exclusive=true;
0760 }
0761
0762 state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
0763 if(current_state==old_state)
0764 {
0765 if(!last_reader)
0766 {
0767 BOOST_VERIFY(winapi::WaitForSingleObjectEx(upgrade_sem,detail::win32::infinite,0)==0);
0768 }
0769 break;
0770 }
0771 old_state=current_state;
0772 }
0773 }
0774
0775 void unlock_and_lock_upgrade()
0776 {
0777 state_data old_state=state;
0778 for(;;)
0779 {
0780 state_data new_state=old_state;
0781 new_state.exclusive=false;
0782 new_state.upgrade=true;
0783 ++new_state.shared_count;
0784 if(new_state.exclusive_waiting)
0785 {
0786 --new_state.exclusive_waiting;
0787 new_state.exclusive_waiting_blocked=false;
0788 }
0789 new_state.shared_waiting=0;
0790
0791 state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
0792 if(current_state==old_state)
0793 {
0794 break;
0795 }
0796 old_state=current_state;
0797 }
0798 release_waiters(old_state);
0799 }
0800
0801 void unlock_and_lock_shared()
0802 {
0803 state_data old_state=state;
0804 for(;;)
0805 {
0806 state_data new_state=old_state;
0807 new_state.exclusive=false;
0808 ++new_state.shared_count;
0809 if(new_state.exclusive_waiting)
0810 {
0811 --new_state.exclusive_waiting;
0812 new_state.exclusive_waiting_blocked=false;
0813 }
0814 new_state.shared_waiting=0;
0815
0816 state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
0817 if(current_state==old_state)
0818 {
0819 break;
0820 }
0821 old_state=current_state;
0822 }
0823 release_waiters(old_state);
0824 }
0825 void unlock_upgrade_and_lock_shared()
0826 {
0827 state_data old_state=state;
0828 for(;;)
0829 {
0830 state_data new_state=old_state;
0831 new_state.upgrade=false;
0832 if(new_state.exclusive_waiting)
0833 {
0834 --new_state.exclusive_waiting;
0835 new_state.exclusive_waiting_blocked=false;
0836 }
0837 new_state.shared_waiting=0;
0838
0839 state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
0840 if(current_state==old_state)
0841 {
0842 break;
0843 }
0844 old_state=current_state;
0845 }
0846 release_waiters(old_state);
0847 }
0848
0849 };
0850 typedef shared_mutex upgrade_mutex;
0851
0852 }
0853
0854 #include <boost/config/abi_suffix.hpp>
0855
0856 #endif