]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/thread/include/boost/thread/win32/shared_mutex.hpp
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / thread / include / 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 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
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>
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
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 }
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)
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
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
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
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>
152 bool timed_lock_shared(TimeDuration const & relative_time)
153 {
154 return timed_lock_shared(get_system_time()+relative_time);
155 }
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>
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>
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>
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 }
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
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
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>
403 bool timed_lock(TimeDuration const & relative_time)
404 {
405 return timed_lock(get_system_time()+relative_time);
406 }
407 #endif
408
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
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>
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>
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>
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 }
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
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
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
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
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
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
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
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 }
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