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