]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/thread/v2/shared_mutex.hpp
update sources to ceph Nautilus 14.2.1
[ceph.git] / ceph / src / boost / boost / thread / v2 / shared_mutex.hpp
1 #ifndef BOOST_THREAD_V2_SHARED_MUTEX_HPP
2 #define BOOST_THREAD_V2_SHARED_MUTEX_HPP
3
4 // shared_mutex.hpp
5 //
6 // Copyright Howard Hinnant 2007-2010.
7 // Copyright Vicente J. Botet Escriba 2012.
8 //
9 // Distributed under the Boost Software License, Version 1.0. (See
10 // accompanying file LICENSE_1_0.txt or copy at
11 // http://www.boost.org/LICENSE_1_0.txt)
12
13 /*
14 <shared_mutex> synopsis
15
16 namespace boost
17 {
18 namespace thread_v2
19 {
20
21 class shared_mutex
22 {
23 public:
24
25 shared_mutex();
26 ~shared_mutex();
27
28 shared_mutex(const shared_mutex&) = delete;
29 shared_mutex& operator=(const shared_mutex&) = delete;
30
31 // Exclusive ownership
32
33 void lock();
34 bool try_lock();
35 template <class Rep, class Period>
36 bool try_lock_for(const boost::chrono::duration<Rep, Period>& rel_time);
37 template <class Clock, class Duration>
38 bool
39 try_lock_until(
40 const boost::chrono::time_point<Clock, Duration>& abs_time);
41 void unlock();
42
43 // Shared ownership
44
45 void lock_shared();
46 bool try_lock_shared();
47 template <class Rep, class Period>
48 bool
49 try_lock_shared_for(const boost::chrono::duration<Rep, Period>& rel_time);
50 template <class Clock, class Duration>
51 bool
52 try_lock_shared_until(
53 const boost::chrono::time_point<Clock, Duration>& abs_time);
54 void unlock_shared();
55 };
56
57 class upgrade_mutex
58 {
59 public:
60
61 upgrade_mutex();
62 ~upgrade_mutex();
63
64 upgrade_mutex(const upgrade_mutex&) = delete;
65 upgrade_mutex& operator=(const upgrade_mutex&) = delete;
66
67 // Exclusive ownership
68
69 void lock();
70 bool try_lock();
71 template <class Rep, class Period>
72 bool try_lock_for(const boost::chrono::duration<Rep, Period>& rel_time);
73 template <class Clock, class Duration>
74 bool
75 try_lock_until(
76 const boost::chrono::time_point<Clock, Duration>& abs_time);
77 void unlock();
78
79 // Shared ownership
80
81 void lock_shared();
82 bool try_lock_shared();
83 template <class Rep, class Period>
84 bool
85 try_lock_shared_for(const boost::chrono::duration<Rep, Period>& rel_time);
86 template <class Clock, class Duration>
87 bool
88 try_lock_shared_until(
89 const boost::chrono::time_point<Clock, Duration>& abs_time);
90 void unlock_shared();
91
92 // Upgrade ownership
93
94 void lock_upgrade();
95 bool try_lock_upgrade();
96 template <class Rep, class Period>
97 bool
98 try_lock_upgrade_for(
99 const boost::chrono::duration<Rep, Period>& rel_time);
100 template <class Clock, class Duration>
101 bool
102 try_lock_upgrade_until(
103 const boost::chrono::time_point<Clock, Duration>& abs_time);
104 void unlock_upgrade();
105
106 // Shared <-> Exclusive
107
108 bool try_unlock_shared_and_lock();
109 template <class Rep, class Period>
110 bool
111 try_unlock_shared_and_lock_for(
112 const boost::chrono::duration<Rep, Period>& rel_time);
113 template <class Clock, class Duration>
114 bool
115 try_unlock_shared_and_lock_until(
116 const boost::chrono::time_point<Clock, Duration>& abs_time);
117 void unlock_and_lock_shared();
118
119 // Shared <-> Upgrade
120
121 bool try_unlock_shared_and_lock_upgrade();
122 template <class Rep, class Period>
123 bool
124 try_unlock_shared_and_lock_upgrade_for(
125 const boost::chrono::duration<Rep, Period>& rel_time);
126 template <class Clock, class Duration>
127 bool
128 try_unlock_shared_and_lock_upgrade_until(
129 const boost::chrono::time_point<Clock, Duration>& abs_time);
130 void unlock_upgrade_and_lock_shared();
131
132 // Upgrade <-> Exclusive
133
134 void unlock_upgrade_and_lock();
135 bool try_unlock_upgrade_and_lock();
136 template <class Rep, class Period>
137 bool
138 try_unlock_upgrade_and_lock_for(
139 const boost::chrono::duration<Rep, Period>& rel_time);
140 template <class Clock, class Duration>
141 bool
142 try_unlock_upgrade_and_lock_until(
143 const boost::chrono::time_point<Clock, Duration>& abs_time);
144 void unlock_and_lock_upgrade();
145 };
146
147 } // thread_v2
148 } // boost
149
150 */
151
152 #include <boost/thread/detail/config.hpp>
153 #include <boost/thread/mutex.hpp>
154 #include <boost/thread/condition_variable.hpp>
155 #include <boost/thread/mutex.hpp>
156 #ifdef BOOST_THREAD_USES_CHRONO
157 #include <boost/chrono.hpp>
158 #endif
159 #include <climits>
160 #include <boost/system/system_error.hpp>
161 #include <boost/bind.hpp>
162
163 namespace boost {
164 namespace thread_v2 {
165
166 class shared_mutex
167 {
168 typedef boost::mutex mutex_t;
169 typedef boost::condition_variable cond_t;
170 typedef unsigned count_t;
171
172 mutex_t mut_;
173 cond_t gate1_;
174 // the gate2_ condition variable is only used by functions that
175 // have taken write_entered_ but are waiting for no_readers()
176 cond_t gate2_;
177 count_t state_;
178
179 static const count_t write_entered_ = 1U << (sizeof(count_t)*CHAR_BIT - 1);
180 static const count_t n_readers_ = ~write_entered_;
181
182 bool no_writer() const
183 {
184 return (state_ & write_entered_) == 0;
185 }
186
187 bool one_writer() const
188 {
189 return (state_ & write_entered_) != 0;
190 }
191
192 bool no_writer_no_readers() const
193 {
194 //return (state_ & write_entered_) == 0 &&
195 // (state_ & n_readers_) == 0;
196 return state_ == 0;
197 }
198
199 bool no_writer_no_max_readers() const
200 {
201 return (state_ & write_entered_) == 0 &&
202 (state_ & n_readers_) != n_readers_;
203 }
204
205 bool no_readers() const
206 {
207 return (state_ & n_readers_) == 0;
208 }
209
210 bool one_or_more_readers() const
211 {
212 return (state_ & n_readers_) > 0;
213 }
214
215 shared_mutex(shared_mutex const&);
216 shared_mutex& operator=(shared_mutex const&);
217
218 public:
219 shared_mutex();
220 ~shared_mutex();
221
222 // Exclusive ownership
223
224 void lock();
225 bool try_lock();
226 #ifdef BOOST_THREAD_USES_CHRONO
227 template <class Rep, class Period>
228 bool try_lock_for(const boost::chrono::duration<Rep, Period>& rel_time)
229 {
230 return try_lock_until(chrono::steady_clock::now() + rel_time);
231 }
232 template <class Clock, class Duration>
233 bool try_lock_until(
234 const boost::chrono::time_point<Clock, Duration>& abs_time);
235 #endif
236 #if defined BOOST_THREAD_USES_DATETIME
237 template<typename T>
238 bool timed_lock(T const & abs_or_rel_time);
239 #endif
240 void unlock();
241
242 // Shared ownership
243
244 void lock_shared();
245 bool try_lock_shared();
246 #ifdef BOOST_THREAD_USES_CHRONO
247 template <class Rep, class Period>
248 bool try_lock_shared_for(const boost::chrono::duration<Rep, Period>& rel_time)
249 {
250 return try_lock_shared_until(chrono::steady_clock::now() + rel_time);
251 }
252 template <class Clock, class Duration>
253 bool try_lock_shared_until(
254 const boost::chrono::time_point<Clock, Duration>& abs_time);
255 #endif
256 #if defined BOOST_THREAD_USES_DATETIME
257 template<typename T>
258 bool timed_lock_shared(T const & abs_or_rel_time);
259 #endif
260 void unlock_shared();
261 };
262
263 inline shared_mutex::shared_mutex()
264 : state_(0)
265 {
266 }
267
268 inline shared_mutex::~shared_mutex()
269 {
270 boost::lock_guard<mutex_t> _(mut_);
271 }
272
273 // Exclusive ownership
274
275 inline void shared_mutex::lock()
276 {
277 boost::unique_lock<mutex_t> lk(mut_);
278 gate1_.wait(lk, boost::bind(&shared_mutex::no_writer, boost::ref(*this)));
279 state_ |= write_entered_;
280 gate2_.wait(lk, boost::bind(&shared_mutex::no_readers, boost::ref(*this)));
281 }
282
283 inline bool shared_mutex::try_lock()
284 {
285 boost::unique_lock<mutex_t> lk(mut_);
286 if (!no_writer_no_readers())
287 {
288 return false;
289 }
290 state_ = write_entered_;
291 return true;
292 }
293
294 #ifdef BOOST_THREAD_USES_CHRONO
295 template <class Clock, class Duration>
296 bool shared_mutex::try_lock_until(
297 const boost::chrono::time_point<Clock, Duration>& abs_time)
298 {
299 boost::unique_lock<mutex_t> lk(mut_);
300 if (!gate1_.wait_until(lk, abs_time, boost::bind(
301 &shared_mutex::no_writer, boost::ref(*this))))
302 {
303 return false;
304 }
305 state_ |= write_entered_;
306 if (!gate2_.wait_until(lk, abs_time, boost::bind(
307 &shared_mutex::no_readers, boost::ref(*this))))
308 {
309 state_ &= ~write_entered_;
310 return false;
311 }
312 return true;
313 }
314 #endif
315
316 #if defined BOOST_THREAD_USES_DATETIME
317 template<typename T>
318 bool shared_mutex::timed_lock(T const & abs_or_rel_time)
319 {
320 boost::unique_lock<mutex_t> lk(mut_);
321 if (!gate1_.timed_wait(lk, abs_or_rel_time, boost::bind(
322 &shared_mutex::no_writer, boost::ref(*this))))
323 {
324 return false;
325 }
326 state_ |= write_entered_;
327 if (!gate2_.timed_wait(lk, abs_or_rel_time, boost::bind(
328 &shared_mutex::no_readers, boost::ref(*this))))
329 {
330 state_ &= ~write_entered_;
331 return false;
332 }
333 return true;
334 }
335 #endif
336
337 inline void shared_mutex::unlock()
338 {
339 boost::lock_guard<mutex_t> _(mut_);
340 BOOST_ASSERT(one_writer());
341 BOOST_ASSERT(no_readers());
342 state_ = 0;
343 // notify all since multiple *lock_shared*() calls may be able
344 // to proceed in response to this notification
345 gate1_.notify_all();
346 }
347
348 // Shared ownership
349
350 inline void shared_mutex::lock_shared()
351 {
352 boost::unique_lock<mutex_t> lk(mut_);
353 gate1_.wait(lk, boost::bind(&shared_mutex::no_writer_no_max_readers, boost::ref(*this)));
354 count_t num_readers = (state_ & n_readers_) + 1;
355 state_ &= ~n_readers_;
356 state_ |= num_readers;
357 }
358
359 inline bool shared_mutex::try_lock_shared()
360 {
361 boost::unique_lock<mutex_t> lk(mut_);
362 if (!no_writer_no_max_readers())
363 {
364 return false;
365 }
366 count_t num_readers = (state_ & n_readers_) + 1;
367 state_ &= ~n_readers_;
368 state_ |= num_readers;
369 return true;
370 }
371
372 #ifdef BOOST_THREAD_USES_CHRONO
373 template <class Clock, class Duration>
374 bool shared_mutex::try_lock_shared_until(
375 const boost::chrono::time_point<Clock, Duration>& abs_time)
376 {
377 boost::unique_lock<mutex_t> lk(mut_);
378 if (!gate1_.wait_until(lk, abs_time, boost::bind(
379 &shared_mutex::no_writer_no_max_readers, boost::ref(*this))))
380 {
381 return false;
382 }
383 count_t num_readers = (state_ & n_readers_) + 1;
384 state_ &= ~n_readers_;
385 state_ |= num_readers;
386 return true;
387 }
388 #endif
389
390 #if defined BOOST_THREAD_USES_DATETIME
391 template<typename T>
392 bool shared_mutex::timed_lock_shared(T const & abs_or_rel_time)
393 {
394 boost::unique_lock<mutex_t> lk(mut_);
395 if (!gate1_.timed_wait(lk, abs_or_rel_time, boost::bind(
396 &shared_mutex::no_writer_no_max_readers, boost::ref(*this))))
397 {
398 return false;
399 }
400 count_t num_readers = (state_ & n_readers_) + 1;
401 state_ &= ~n_readers_;
402 state_ |= num_readers;
403 return true;
404 }
405 #endif
406
407 inline void shared_mutex::unlock_shared()
408 {
409 boost::lock_guard<mutex_t> _(mut_);
410 BOOST_ASSERT(one_or_more_readers());
411 count_t num_readers = (state_ & n_readers_) - 1;
412 state_ &= ~n_readers_;
413 state_ |= num_readers;
414 if (no_writer())
415 {
416 if (num_readers == n_readers_ - 1)
417 gate1_.notify_one();
418 }
419 else
420 {
421 if (num_readers == 0)
422 gate2_.notify_one();
423 }
424 }
425
426 } // thread_v2
427 } // boost
428
429 namespace boost {
430 namespace thread_v2 {
431
432 class upgrade_mutex
433 {
434 typedef boost::mutex mutex_t;
435 typedef boost::condition_variable cond_t;
436 typedef unsigned count_t;
437
438 mutex_t mut_;
439 cond_t gate1_;
440 // the gate2_ condition variable is only used by functions that
441 // have taken write_entered_ but are waiting for no_readers()
442 cond_t gate2_;
443 count_t state_;
444
445 static const unsigned write_entered_ = 1U << (sizeof(count_t)*CHAR_BIT - 1);
446 static const unsigned upgradable_entered_ = write_entered_ >> 1;
447 static const unsigned n_readers_ = ~(write_entered_ | upgradable_entered_);
448
449 bool no_writer() const
450 {
451 return (state_ & write_entered_) == 0;
452 }
453
454 bool one_writer() const
455 {
456 return (state_ & write_entered_) != 0;
457 }
458
459 bool no_writer_no_max_readers() const
460 {
461 return (state_ & write_entered_) == 0 &&
462 (state_ & n_readers_) != n_readers_;
463 }
464
465 bool no_writer_no_upgrader() const
466 {
467 return (state_ & (write_entered_ | upgradable_entered_)) == 0;
468 }
469
470 bool no_writer_no_upgrader_no_readers() const
471 {
472 //return (state_ & (write_entered_ | upgradable_entered_)) == 0 &&
473 // (state_ & n_readers_) == 0;
474 return state_ == 0;
475 }
476
477 bool no_writer_no_upgrader_one_reader() const
478 {
479 //return (state_ & (write_entered_ | upgradable_entered_)) == 0 &&
480 // (state_ & n_readers_) == 1;
481 return state_ == 1;
482 }
483
484 bool no_writer_no_upgrader_no_max_readers() const
485 {
486 return (state_ & (write_entered_ | upgradable_entered_)) == 0 &&
487 (state_ & n_readers_) != n_readers_;
488 }
489
490 bool no_upgrader() const
491 {
492 return (state_ & upgradable_entered_) == 0;
493 }
494
495 bool one_upgrader() const
496 {
497 return (state_ & upgradable_entered_) != 0;
498 }
499
500 bool no_readers() const
501 {
502 return (state_ & n_readers_) == 0;
503 }
504
505 bool one_reader() const
506 {
507 return (state_ & n_readers_) == 1;
508 }
509
510 bool one_or_more_readers() const
511 {
512 return (state_ & n_readers_) > 0;
513 }
514
515 upgrade_mutex(const upgrade_mutex&);
516 upgrade_mutex& operator=(const upgrade_mutex&);
517
518 public:
519 upgrade_mutex();
520 ~upgrade_mutex();
521
522 // Exclusive ownership
523
524 void lock();
525 bool try_lock();
526 #ifdef BOOST_THREAD_USES_CHRONO
527 template <class Rep, class Period>
528 bool try_lock_for(const boost::chrono::duration<Rep, Period>& rel_time)
529 {
530 return try_lock_until(chrono::steady_clock::now() + rel_time);
531 }
532 template <class Clock, class Duration>
533 bool try_lock_until(
534 const boost::chrono::time_point<Clock, Duration>& abs_time);
535 #endif
536 #if defined BOOST_THREAD_USES_DATETIME
537 template<typename T>
538 bool timed_lock(T const & abs_or_rel_time);
539 #endif
540 void unlock();
541
542 // Shared ownership
543
544 void lock_shared();
545 bool try_lock_shared();
546 #ifdef BOOST_THREAD_USES_CHRONO
547 template <class Rep, class Period>
548 bool try_lock_shared_for(const boost::chrono::duration<Rep, Period>& rel_time)
549 {
550 return try_lock_shared_until(chrono::steady_clock::now() + rel_time);
551 }
552 template <class Clock, class Duration>
553 bool try_lock_shared_until(
554 const boost::chrono::time_point<Clock, Duration>& abs_time);
555 #endif
556 #if defined BOOST_THREAD_USES_DATETIME
557 template<typename T>
558 bool timed_lock_shared(T const & abs_or_rel_time);
559 #endif
560 void unlock_shared();
561
562 // Upgrade ownership
563
564 void lock_upgrade();
565 bool try_lock_upgrade();
566 #ifdef BOOST_THREAD_USES_CHRONO
567 template <class Rep, class Period>
568 bool try_lock_upgrade_for(
569 const boost::chrono::duration<Rep, Period>& rel_time)
570 {
571 return try_lock_upgrade_until(chrono::steady_clock::now() + rel_time);
572 }
573 template <class Clock, class Duration>
574 bool try_lock_upgrade_until(
575 const boost::chrono::time_point<Clock, Duration>& abs_time);
576 #endif
577 #if defined BOOST_THREAD_USES_DATETIME
578 template<typename T>
579 bool timed_lock_upgrade(T const & abs_or_rel_time);
580 #endif
581 void unlock_upgrade();
582
583 // Shared <-> Exclusive
584
585 #ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS
586 //bool unlock_shared_and_lock(); // can cause a deadlock if used
587 bool try_unlock_shared_and_lock();
588 #ifdef BOOST_THREAD_USES_CHRONO
589 template <class Rep, class Period>
590 bool try_unlock_shared_and_lock_for(
591 const boost::chrono::duration<Rep, Period>& rel_time)
592 {
593 return try_unlock_shared_and_lock_until(chrono::steady_clock::now() + rel_time);
594 }
595 template <class Clock, class Duration>
596 bool try_unlock_shared_and_lock_until(
597 const boost::chrono::time_point<Clock, Duration>& abs_time);
598 #endif
599 #endif
600 void unlock_and_lock_shared();
601
602 // Shared <-> Upgrade
603
604 #ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS
605 //bool unlock_shared_and_lock_upgrade(); // can cause a deadlock if used
606 bool try_unlock_shared_and_lock_upgrade();
607 #ifdef BOOST_THREAD_USES_CHRONO
608 template <class Rep, class Period>
609 bool try_unlock_shared_and_lock_upgrade_for(
610 const boost::chrono::duration<Rep, Period>& rel_time)
611 {
612 return try_unlock_shared_and_lock_upgrade_until(chrono::steady_clock::now() + rel_time);
613 }
614 template <class Clock, class Duration>
615 bool try_unlock_shared_and_lock_upgrade_until(
616 const boost::chrono::time_point<Clock, Duration>& abs_time);
617 #endif
618 #endif
619 void unlock_upgrade_and_lock_shared();
620
621 // Upgrade <-> Exclusive
622
623 void unlock_upgrade_and_lock();
624 bool try_unlock_upgrade_and_lock();
625 #ifdef BOOST_THREAD_USES_CHRONO
626 template <class Rep, class Period>
627 bool try_unlock_upgrade_and_lock_for(
628 const boost::chrono::duration<Rep, Period>& rel_time)
629 {
630 return try_unlock_upgrade_and_lock_until(chrono::steady_clock::now() + rel_time);
631 }
632 template <class Clock, class Duration>
633 bool try_unlock_upgrade_and_lock_until(
634 const boost::chrono::time_point<Clock, Duration>& abs_time);
635 #endif
636 void unlock_and_lock_upgrade();
637 };
638
639 inline upgrade_mutex::upgrade_mutex()
640 : gate1_(),
641 gate2_(),
642 state_(0)
643 {
644 }
645
646 inline upgrade_mutex::~upgrade_mutex()
647 {
648 boost::lock_guard<mutex_t> _(mut_);
649 }
650
651 // Exclusive ownership
652
653 inline void upgrade_mutex::lock()
654 {
655 boost::unique_lock<mutex_t> lk(mut_);
656 gate1_.wait(lk, boost::bind(&upgrade_mutex::no_writer_no_upgrader, boost::ref(*this)));
657 state_ |= write_entered_;
658 gate2_.wait(lk, boost::bind(&upgrade_mutex::no_readers, boost::ref(*this)));
659 }
660
661 inline bool upgrade_mutex::try_lock()
662 {
663 boost::unique_lock<mutex_t> lk(mut_);
664 if (!no_writer_no_upgrader_no_readers())
665 {
666 return false;
667 }
668 state_ = write_entered_;
669 return true;
670 }
671
672 #ifdef BOOST_THREAD_USES_CHRONO
673 template <class Clock, class Duration>
674 bool upgrade_mutex::try_lock_until(
675 const boost::chrono::time_point<Clock, Duration>& abs_time)
676 {
677 boost::unique_lock<mutex_t> lk(mut_);
678 if (!gate1_.wait_until(lk, abs_time, boost::bind(
679 &upgrade_mutex::no_writer_no_upgrader, boost::ref(*this))))
680 {
681 return false;
682 }
683 state_ |= write_entered_;
684 if (!gate2_.wait_until(lk, abs_time, boost::bind(
685 &upgrade_mutex::no_readers, boost::ref(*this))))
686 {
687 state_ &= ~write_entered_;
688 return false;
689 }
690 return true;
691 }
692 #endif
693
694 #if defined BOOST_THREAD_USES_DATETIME
695 template<typename T>
696 bool upgrade_mutex::timed_lock(T const & abs_or_rel_time)
697 {
698 boost::unique_lock<mutex_t> lk(mut_);
699 if (!gate1_.timed_wait(lk, abs_or_rel_time, boost::bind(
700 &upgrade_mutex::no_writer_no_upgrader, boost::ref(*this))))
701 {
702 return false;
703 }
704 state_ |= write_entered_;
705 if (!gate2_.timed_wait(lk, abs_or_rel_time, boost::bind(
706 &upgrade_mutex::no_readers, boost::ref(*this))))
707 {
708 state_ &= ~write_entered_;
709 return false;
710 }
711 return true;
712 }
713 #endif
714
715 inline void upgrade_mutex::unlock()
716 {
717 boost::lock_guard<mutex_t> _(mut_);
718 BOOST_ASSERT(one_writer());
719 BOOST_ASSERT(no_upgrader());
720 BOOST_ASSERT(no_readers());
721 state_ = 0;
722 // notify all since multiple *lock_shared*() calls and a *lock_upgrade*()
723 // call may be able to proceed in response to this notification
724 gate1_.notify_all();
725 }
726
727 // Shared ownership
728
729 inline void upgrade_mutex::lock_shared()
730 {
731 boost::unique_lock<mutex_t> lk(mut_);
732 gate1_.wait(lk, boost::bind(&upgrade_mutex::no_writer_no_max_readers, boost::ref(*this)));
733 count_t num_readers = (state_ & n_readers_) + 1;
734 state_ &= ~n_readers_;
735 state_ |= num_readers;
736 }
737
738 inline bool upgrade_mutex::try_lock_shared()
739 {
740 boost::unique_lock<mutex_t> lk(mut_);
741 if (!no_writer_no_max_readers())
742 {
743 return false;
744 }
745 count_t num_readers = (state_ & n_readers_) + 1;
746 state_ &= ~n_readers_;
747 state_ |= num_readers;
748 return true;
749 }
750
751 #ifdef BOOST_THREAD_USES_CHRONO
752 template <class Clock, class Duration>
753 bool upgrade_mutex::try_lock_shared_until(
754 const boost::chrono::time_point<Clock, Duration>& abs_time)
755 {
756 boost::unique_lock<mutex_t> lk(mut_);
757 if (!gate1_.wait_until(lk, abs_time, boost::bind(
758 &upgrade_mutex::no_writer_no_max_readers, boost::ref(*this))))
759 {
760 return false;
761 }
762 count_t num_readers = (state_ & n_readers_) + 1;
763 state_ &= ~n_readers_;
764 state_ |= num_readers;
765 return true;
766 }
767 #endif
768
769 #if defined BOOST_THREAD_USES_DATETIME
770 template<typename T>
771 bool upgrade_mutex::timed_lock_shared(T const & abs_or_rel_time)
772 {
773 boost::unique_lock<mutex_t> lk(mut_);
774 if (!gate1_.timed_wait(lk, abs_or_rel_time, boost::bind(
775 &upgrade_mutex::no_writer_no_max_readers, boost::ref(*this))))
776 {
777 return false;
778 }
779 count_t num_readers = (state_ & n_readers_) + 1;
780 state_ &= ~n_readers_;
781 state_ |= num_readers;
782 return true;
783 }
784 #endif
785
786 inline void upgrade_mutex::unlock_shared()
787 {
788 boost::lock_guard<mutex_t> _(mut_);
789 BOOST_ASSERT(one_or_more_readers());
790 count_t num_readers = (state_ & n_readers_) - 1;
791 state_ &= ~n_readers_;
792 state_ |= num_readers;
793 if (no_writer())
794 {
795 if (num_readers == n_readers_ - 1)
796 gate1_.notify_one();
797 }
798 else
799 {
800 if (num_readers == 0)
801 gate2_.notify_one();
802 }
803 }
804
805 // Upgrade ownership
806
807 inline void upgrade_mutex::lock_upgrade()
808 {
809 boost::unique_lock<mutex_t> lk(mut_);
810 gate1_.wait(lk, boost::bind(&upgrade_mutex::no_writer_no_upgrader_no_max_readers, boost::ref(*this)));
811 count_t num_readers = (state_ & n_readers_) + 1;
812 state_ &= ~n_readers_;
813 state_ |= upgradable_entered_ | num_readers;
814 }
815
816 inline bool upgrade_mutex::try_lock_upgrade()
817 {
818 boost::unique_lock<mutex_t> lk(mut_);
819 if (!no_writer_no_upgrader_no_max_readers())
820 {
821 return false;
822 }
823 count_t num_readers = (state_ & n_readers_) + 1;
824 state_ &= ~n_readers_;
825 state_ |= upgradable_entered_ | num_readers;
826 return true;
827 }
828
829 #ifdef BOOST_THREAD_USES_CHRONO
830 template <class Clock, class Duration>
831 bool upgrade_mutex::try_lock_upgrade_until(
832 const boost::chrono::time_point<Clock, Duration>& abs_time)
833 {
834 boost::unique_lock<mutex_t> lk(mut_);
835 if (!gate1_.wait_until(lk, abs_time, boost::bind(
836 &upgrade_mutex::no_writer_no_upgrader_no_max_readers, boost::ref(*this))))
837 {
838 return false;
839 }
840 count_t num_readers = (state_ & n_readers_) + 1;
841 state_ &= ~n_readers_;
842 state_ |= upgradable_entered_ | num_readers;
843 return true;
844 }
845 #endif
846
847 #if defined BOOST_THREAD_USES_DATETIME
848 template<typename T>
849 bool upgrade_mutex::timed_lock_upgrade(T const & abs_or_rel_time)
850 {
851 boost::unique_lock<mutex_t> lk(mut_);
852 if (!gate1_.timed_wait(lk, abs_or_rel_time, boost::bind(
853 &upgrade_mutex::no_writer_no_upgrader_no_max_readers, boost::ref(*this))))
854 {
855 return false;
856 }
857 count_t num_readers = (state_ & n_readers_) + 1;
858 state_ &= ~n_readers_;
859 state_ |= upgradable_entered_ | num_readers;
860 return true;
861 }
862 #endif
863
864 inline void upgrade_mutex::unlock_upgrade()
865 {
866 boost::lock_guard<mutex_t> _(mut_);
867 BOOST_ASSERT(no_writer());
868 BOOST_ASSERT(one_upgrader());
869 BOOST_ASSERT(one_or_more_readers());
870 count_t num_readers = (state_ & n_readers_) - 1;
871 state_ &= ~(upgradable_entered_ | n_readers_);
872 state_ |= num_readers;
873 // notify all since both a *lock*() and a *lock_shared*() call
874 // may be able to proceed in response to this notification
875 gate1_.notify_all();
876 }
877
878 // Shared <-> Exclusive
879
880 #ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS
881 inline bool upgrade_mutex::try_unlock_shared_and_lock()
882 {
883 boost::unique_lock<mutex_t> lk(mut_);
884 BOOST_ASSERT(one_or_more_readers());
885 if (!no_writer_no_upgrader_one_reader())
886 {
887 return false;
888 }
889 state_ = write_entered_;
890 return true;
891 }
892
893 #ifdef BOOST_THREAD_USES_CHRONO
894 template <class Clock, class Duration>
895 bool upgrade_mutex::try_unlock_shared_and_lock_until(
896 const boost::chrono::time_point<Clock, Duration>& abs_time)
897 {
898 boost::unique_lock<mutex_t> lk(mut_);
899 BOOST_ASSERT(one_or_more_readers());
900 if (!gate1_.wait_until(lk, abs_time, boost::bind(
901 &upgrade_mutex::no_writer_no_upgrader, boost::ref(*this))))
902 {
903 return false;
904 }
905 count_t num_readers = (state_ & n_readers_) - 1;
906 state_ &= ~n_readers_;
907 state_ |= (write_entered_ | num_readers);
908 if (!gate2_.wait_until(lk, abs_time, boost::bind(
909 &upgrade_mutex::no_readers, boost::ref(*this))))
910 {
911 ++num_readers;
912 state_ &= ~(write_entered_ | n_readers_);
913 state_ |= num_readers;
914 return false;
915 }
916 return true;
917 }
918 #endif
919 #endif
920
921 inline void upgrade_mutex::unlock_and_lock_shared()
922 {
923 boost::lock_guard<mutex_t> _(mut_);
924 BOOST_ASSERT(one_writer());
925 BOOST_ASSERT(no_upgrader());
926 BOOST_ASSERT(no_readers());
927 state_ = 1;
928 // notify all since multiple *lock_shared*() calls and a *lock_upgrade*()
929 // call may be able to proceed in response to this notification
930 gate1_.notify_all();
931 }
932
933 // Shared <-> Upgrade
934
935 #ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS
936 inline bool upgrade_mutex::try_unlock_shared_and_lock_upgrade()
937 {
938 boost::unique_lock<mutex_t> lk(mut_);
939 BOOST_ASSERT(one_or_more_readers());
940 if (!no_writer_no_upgrader())
941 {
942 return false;
943 }
944 state_ |= upgradable_entered_;
945 return true;
946 }
947
948 #ifdef BOOST_THREAD_USES_CHRONO
949 template <class Clock, class Duration>
950 bool upgrade_mutex::try_unlock_shared_and_lock_upgrade_until(
951 const boost::chrono::time_point<Clock, Duration>& abs_time)
952 {
953 boost::unique_lock<mutex_t> lk(mut_);
954 BOOST_ASSERT(one_or_more_readers());
955 if (!gate1_.wait_until(lk, abs_time, boost::bind(
956 &upgrade_mutex::no_writer_no_upgrader, boost::ref(*this))))
957 {
958 return false;
959 }
960 state_ |= upgradable_entered_;
961 return true;
962 }
963 #endif
964 #endif
965
966 inline void upgrade_mutex::unlock_upgrade_and_lock_shared()
967 {
968 boost::lock_guard<mutex_t> _(mut_);
969 BOOST_ASSERT(no_writer());
970 BOOST_ASSERT(one_upgrader());
971 BOOST_ASSERT(one_or_more_readers());
972 state_ &= ~upgradable_entered_;
973 // notify all since only one *lock*() or *lock_upgrade*() call can win and
974 // proceed in response to this notification, but a *lock_shared*() call may
975 // also be waiting and could steal the notification
976 gate1_.notify_all();
977 }
978
979 // Upgrade <-> Exclusive
980
981 inline void upgrade_mutex::unlock_upgrade_and_lock()
982 {
983 boost::unique_lock<mutex_t> lk(mut_);
984 BOOST_ASSERT(no_writer());
985 BOOST_ASSERT(one_upgrader());
986 BOOST_ASSERT(one_or_more_readers());
987 count_t num_readers = (state_ & n_readers_) - 1;
988 state_ &= ~(upgradable_entered_ | n_readers_);
989 state_ |= write_entered_ | num_readers;
990 gate2_.wait(lk, boost::bind(&upgrade_mutex::no_readers, boost::ref(*this)));
991 }
992
993 inline bool upgrade_mutex::try_unlock_upgrade_and_lock()
994 {
995 boost::unique_lock<mutex_t> lk(mut_);
996 BOOST_ASSERT(no_writer());
997 BOOST_ASSERT(one_upgrader());
998 BOOST_ASSERT(one_or_more_readers());
999 if (!one_reader())
1000 {
1001 return false;
1002 }
1003 state_ = write_entered_;
1004 return true;
1005 }
1006
1007 #ifdef BOOST_THREAD_USES_CHRONO
1008 template <class Clock, class Duration>
1009 bool upgrade_mutex::try_unlock_upgrade_and_lock_until(
1010 const boost::chrono::time_point<Clock, Duration>& abs_time)
1011 {
1012 boost::unique_lock<mutex_t> lk(mut_);
1013 BOOST_ASSERT(no_writer());
1014 BOOST_ASSERT(one_upgrader());
1015 BOOST_ASSERT(one_or_more_readers());
1016 count_t num_readers = (state_ & n_readers_) - 1;
1017 state_ &= ~(upgradable_entered_ | n_readers_);
1018 state_ |= (write_entered_ | num_readers);
1019 if (!gate2_.wait_until(lk, abs_time, boost::bind(
1020 &upgrade_mutex::no_readers, boost::ref(*this))))
1021 {
1022 ++num_readers;
1023 state_ &= ~(write_entered_ | n_readers_);
1024 state_ |= (upgradable_entered_ | num_readers);
1025 return false;
1026 }
1027 return true;
1028 }
1029 #endif
1030
1031 inline void upgrade_mutex::unlock_and_lock_upgrade()
1032 {
1033 boost::lock_guard<mutex_t> _(mut_);
1034 BOOST_ASSERT(one_writer());
1035 BOOST_ASSERT(no_upgrader());
1036 BOOST_ASSERT(no_readers());
1037 state_ = upgradable_entered_ | 1;
1038 // notify all since multiple *lock_shared*() calls may be able
1039 // to proceed in response to this notification
1040 gate1_.notify_all();
1041 }
1042
1043 } // thread_v2
1044 } // boost
1045
1046 namespace boost {
1047 //using thread_v2::shared_mutex;
1048 using thread_v2::upgrade_mutex;
1049 typedef thread_v2::upgrade_mutex shared_mutex;
1050 }
1051
1052 #endif