]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/interprocess/sync/interprocess_upgradable_mutex.hpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / boost / interprocess / sync / interprocess_upgradable_mutex.hpp
1 ////////////////////////////////////////////////////////////////////////////////
2 //
3 // Code based on Howard Hinnant's upgrade_mutex class
4 //
5 // (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
6 // Software License, Version 1.0. (See accompanying file
7 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
8 //
9 // See http://www.boost.org/libs/interprocess for documentation.
10 //
11 //////////////////////////////////////////////////////////////////////////////
12
13 #ifndef BOOST_INTERPROCESS_UPGRADABLE_MUTEX_HPP
14 #define BOOST_INTERPROCESS_UPGRADABLE_MUTEX_HPP
15
16 #ifndef BOOST_CONFIG_HPP
17 # include <boost/config.hpp>
18 #endif
19 #
20 #if defined(BOOST_HAS_PRAGMA_ONCE)
21 # pragma once
22 #endif
23
24 #include <boost/interprocess/detail/config_begin.hpp>
25 #include <boost/interprocess/detail/workaround.hpp>
26 #include <boost/interprocess/sync/scoped_lock.hpp>
27 #include <boost/interprocess/detail/posix_time_types_wrk.hpp>
28 #include <boost/interprocess/sync/interprocess_mutex.hpp>
29 #include <boost/interprocess/sync/interprocess_condition.hpp>
30 #include <climits>
31
32
33 //!\file
34 //!Describes interprocess_upgradable_mutex class
35
36 namespace boost {
37 namespace interprocess {
38
39 //!Wraps a interprocess_upgradable_mutex that can be placed in shared memory and can be
40 //!shared between processes. Allows timed lock tries
41 class interprocess_upgradable_mutex
42 {
43 //Non-copyable
44 interprocess_upgradable_mutex(const interprocess_upgradable_mutex &);
45 interprocess_upgradable_mutex &operator=(const interprocess_upgradable_mutex &);
46
47 friend class interprocess_condition;
48 public:
49
50 //!Constructs the upgradable lock.
51 //!Throws interprocess_exception on error.
52 interprocess_upgradable_mutex();
53
54 //!Destroys the upgradable lock.
55 //!Does not throw.
56 ~interprocess_upgradable_mutex();
57
58 //Exclusive locking
59
60 //!Effects: The calling thread tries to obtain exclusive ownership of the mutex,
61 //! and if another thread has exclusive, sharable or upgradable ownership of
62 //! the mutex, it waits until it can obtain the ownership.
63 //!Throws: interprocess_exception on error.
64 void lock();
65
66 //!Effects: The calling thread tries to acquire exclusive ownership of the mutex
67 //! without waiting. If no other thread has exclusive, sharable or upgradable
68 //! ownership of the mutex this succeeds.
69 //!Returns: If it can acquire exclusive ownership immediately returns true.
70 //! If it has to wait, returns false.
71 //!Throws: interprocess_exception on error.
72 bool try_lock();
73
74 //!Effects: The calling thread tries to acquire exclusive ownership of the mutex
75 //! waiting if necessary until no other thread has exclusive, sharable or
76 //! upgradable ownership of the mutex or abs_time is reached.
77 //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false.
78 //!Throws: interprocess_exception on error.
79 bool timed_lock(const boost::posix_time::ptime &abs_time);
80
81 //!Precondition: The thread must have exclusive ownership of the mutex.
82 //!Effects: The calling thread releases the exclusive ownership of the mutex.
83 //!Throws: An exception derived from interprocess_exception on error.
84 void unlock();
85
86 //Sharable locking
87
88 //!Effects: The calling thread tries to obtain sharable ownership of the mutex,
89 //! and if another thread has exclusive ownership of the mutex,
90 //! waits until it can obtain the ownership.
91 //!Throws: interprocess_exception on error.
92 void lock_sharable();
93
94 //!Effects: The calling thread tries to acquire sharable ownership of the mutex
95 //! without waiting. If no other thread has exclusive ownership
96 //! of the mutex this succeeds.
97 //!Returns: If it can acquire sharable ownership immediately returns true. If it
98 //! has to wait, returns false.
99 //!Throws: interprocess_exception on error.
100 bool try_lock_sharable();
101
102 //!Effects: The calling thread tries to acquire sharable ownership of the mutex
103 //! waiting if necessary until no other thread has exclusive
104 //! ownership of the mutex or abs_time is reached.
105 //!Returns: If acquires sharable ownership, returns true. Otherwise returns false.
106 //!Throws: interprocess_exception on error.
107 bool timed_lock_sharable(const boost::posix_time::ptime &abs_time);
108
109 //!Precondition: The thread must have sharable ownership of the mutex.
110 //!Effects: The calling thread releases the sharable ownership of the mutex.
111 //!Throws: An exception derived from interprocess_exception on error.
112 void unlock_sharable();
113
114 //Upgradable locking
115
116 //!Effects: The calling thread tries to obtain upgradable ownership of the mutex,
117 //! and if another thread has exclusive or upgradable ownership of the mutex,
118 //! waits until it can obtain the ownership.
119 //!Throws: interprocess_exception on error.
120 void lock_upgradable();
121
122 //!Effects: The calling thread tries to acquire upgradable ownership of the mutex
123 //! without waiting. If no other thread has exclusive or upgradable ownership
124 //! of the mutex this succeeds.
125 //!Returns: If it can acquire upgradable ownership immediately returns true.
126 //! If it has to wait, returns false.
127 //!Throws: interprocess_exception on error.
128 bool try_lock_upgradable();
129
130 //!Effects: The calling thread tries to acquire upgradable ownership of the mutex
131 //! waiting if necessary until no other thread has exclusive or upgradable
132 //! ownership of the mutex or abs_time is reached.
133 //!Returns: If acquires upgradable ownership, returns true. Otherwise returns false.
134 //!Throws: interprocess_exception on error.
135 bool timed_lock_upgradable(const boost::posix_time::ptime &abs_time);
136
137 //!Precondition: The thread must have upgradable ownership of the mutex.
138 //!Effects: The calling thread releases the upgradable ownership of the mutex.
139 //!Throws: An exception derived from interprocess_exception on error.
140 void unlock_upgradable();
141
142 //Demotions
143
144 //!Precondition: The thread must have exclusive ownership of the mutex.
145 //!Effects: The thread atomically releases exclusive ownership and acquires
146 //! upgradable ownership. This operation is non-blocking.
147 //!Throws: An exception derived from interprocess_exception on error.
148 void unlock_and_lock_upgradable();
149
150 //!Precondition: The thread must have exclusive ownership of the mutex.
151 //!Effects: The thread atomically releases exclusive ownership and acquires
152 //! sharable ownership. This operation is non-blocking.
153 //!Throws: An exception derived from interprocess_exception on error.
154 void unlock_and_lock_sharable();
155
156 //!Precondition: The thread must have upgradable ownership of the mutex.
157 //!Effects: The thread atomically releases upgradable ownership and acquires
158 //! sharable ownership. This operation is non-blocking.
159 //!Throws: An exception derived from interprocess_exception on error.
160 void unlock_upgradable_and_lock_sharable();
161
162 //Promotions
163
164 //!Precondition: The thread must have upgradable ownership of the mutex.
165 //!Effects: The thread atomically releases upgradable ownership and acquires
166 //! exclusive ownership. This operation will block until all threads with
167 //! sharable ownership release their sharable lock.
168 //!Throws: An exception derived from interprocess_exception on error.
169 void unlock_upgradable_and_lock();
170
171 //!Precondition: The thread must have upgradable ownership of the mutex.
172 //!Effects: The thread atomically releases upgradable ownership and tries to
173 //! acquire exclusive ownership. This operation will fail if there are threads
174 //! with sharable ownership, but it will maintain upgradable ownership.
175 //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false.
176 //!Throws: An exception derived from interprocess_exception on error.
177 bool try_unlock_upgradable_and_lock();
178
179 //!Precondition: The thread must have upgradable ownership of the mutex.
180 //!Effects: The thread atomically releases upgradable ownership and tries to acquire
181 //! exclusive ownership, waiting if necessary until abs_time. This operation will
182 //! fail if there are threads with sharable ownership or timeout reaches, but it
183 //! will maintain upgradable ownership.
184 //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false.
185 //!Throws: An exception derived from interprocess_exception on error. */
186 bool timed_unlock_upgradable_and_lock(const boost::posix_time::ptime &abs_time);
187
188 //!Precondition: The thread must have sharable ownership of the mutex.
189 //!Effects: The thread atomically releases sharable ownership and tries to acquire
190 //! exclusive ownership. This operation will fail if there are threads with sharable
191 //! or upgradable ownership, but it will maintain sharable ownership.
192 //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false.
193 //!Throws: An exception derived from interprocess_exception on error.
194 bool try_unlock_sharable_and_lock();
195
196 //!Precondition: The thread must have sharable ownership of the mutex.
197 //!Effects: The thread atomically releases sharable ownership and tries to acquire
198 //! upgradable ownership. This operation will fail if there are threads with sharable
199 //! or upgradable ownership, but it will maintain sharable ownership.
200 //!Returns: If acquires upgradable ownership, returns true. Otherwise returns false.
201 //!Throws: An exception derived from interprocess_exception on error.
202 bool try_unlock_sharable_and_lock_upgradable();
203
204 #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
205 private:
206 typedef scoped_lock<interprocess_mutex> scoped_lock_t;
207
208 //Pack all the control data in a word to be able
209 //to use atomic instructions in the future
210 struct control_word_t
211 {
212 unsigned exclusive_in : 1;
213 unsigned upgradable_in : 1;
214 unsigned num_upr_shar : sizeof(unsigned)*CHAR_BIT-2;
215 } m_ctrl;
216
217 interprocess_mutex m_mut;
218 interprocess_condition m_first_gate;
219 interprocess_condition m_second_gate;
220
221 private:
222 //Rollback structures for exceptions or failure return values
223 struct exclusive_rollback
224 {
225 exclusive_rollback(control_word_t &ctrl
226 ,interprocess_condition &first_gate)
227 : mp_ctrl(&ctrl), m_first_gate(first_gate)
228 {}
229
230 void release()
231 { mp_ctrl = 0; }
232
233 ~exclusive_rollback()
234 {
235 if(mp_ctrl){
236 mp_ctrl->exclusive_in = 0;
237 m_first_gate.notify_all();
238 }
239 }
240 control_word_t *mp_ctrl;
241 interprocess_condition &m_first_gate;
242 };
243
244 struct upgradable_to_exclusive_rollback
245 {
246 upgradable_to_exclusive_rollback(control_word_t &ctrl)
247 : mp_ctrl(&ctrl)
248 {}
249
250 void release()
251 { mp_ctrl = 0; }
252
253 ~upgradable_to_exclusive_rollback()
254 {
255 if(mp_ctrl){
256 //Recover upgradable lock
257 mp_ctrl->upgradable_in = 1;
258 ++mp_ctrl->num_upr_shar;
259 //Execute the second half of exclusive locking
260 mp_ctrl->exclusive_in = 0;
261 }
262 }
263 control_word_t *mp_ctrl;
264 };
265
266 template<int Dummy>
267 struct base_constants_t
268 {
269 static const unsigned max_readers
270 = ~(unsigned(3) << (sizeof(unsigned)*CHAR_BIT-2));
271 };
272 typedef base_constants_t<0> constants;
273 #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
274 };
275
276 #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
277
278 template <int Dummy>
279 const unsigned interprocess_upgradable_mutex::base_constants_t<Dummy>::max_readers;
280
281 inline interprocess_upgradable_mutex::interprocess_upgradable_mutex()
282 {
283 this->m_ctrl.exclusive_in = 0;
284 this->m_ctrl.upgradable_in = 0;
285 this->m_ctrl.num_upr_shar = 0;
286 }
287
288 inline interprocess_upgradable_mutex::~interprocess_upgradable_mutex()
289 {}
290
291 inline void interprocess_upgradable_mutex::lock()
292 {
293 scoped_lock_t lck(m_mut);
294
295 //The exclusive lock must block in the first gate
296 //if an exclusive or upgradable lock has been acquired
297 while (this->m_ctrl.exclusive_in || this->m_ctrl.upgradable_in){
298 this->m_first_gate.wait(lck);
299 }
300
301 //Mark that exclusive lock has been acquired
302 this->m_ctrl.exclusive_in = 1;
303
304 //Prepare rollback
305 exclusive_rollback rollback(this->m_ctrl, this->m_first_gate);
306
307 //Now wait until all readers are gone
308 while (this->m_ctrl.num_upr_shar){
309 this->m_second_gate.wait(lck);
310 }
311 rollback.release();
312 }
313
314 inline bool interprocess_upgradable_mutex::try_lock()
315 {
316 scoped_lock_t lck(m_mut, try_to_lock);
317
318 //If we can't lock or any has there is any exclusive, upgradable
319 //or sharable mark return false;
320 if(!lck.owns()
321 || this->m_ctrl.exclusive_in
322 || this->m_ctrl.num_upr_shar){
323 return false;
324 }
325 this->m_ctrl.exclusive_in = 1;
326 return true;
327 }
328
329 inline bool interprocess_upgradable_mutex::timed_lock
330 (const boost::posix_time::ptime &abs_time)
331 {
332 //Mutexes and condvars handle just fine infinite abs_times
333 //so avoid checking it here
334 scoped_lock_t lck(m_mut, abs_time);
335 if(!lck.owns()) return false;
336
337 //The exclusive lock must block in the first gate
338 //if an exclusive or upgradable lock has been acquired
339 while (this->m_ctrl.exclusive_in || this->m_ctrl.upgradable_in){
340 if(!this->m_first_gate.timed_wait(lck, abs_time)){
341 if(this->m_ctrl.exclusive_in || this->m_ctrl.upgradable_in){
342 return false;
343 }
344 break;
345 }
346 }
347
348 //Mark that exclusive lock has been acquired
349 this->m_ctrl.exclusive_in = 1;
350
351 //Prepare rollback
352 exclusive_rollback rollback(this->m_ctrl, this->m_first_gate);
353
354 //Now wait until all readers are gone
355 while (this->m_ctrl.num_upr_shar){
356 if(!this->m_second_gate.timed_wait(lck, abs_time)){
357 if(this->m_ctrl.num_upr_shar){
358 return false;
359 }
360 break;
361 }
362 }
363 rollback.release();
364 return true;
365 }
366
367 inline void interprocess_upgradable_mutex::unlock()
368 {
369 scoped_lock_t lck(m_mut);
370 this->m_ctrl.exclusive_in = 0;
371 this->m_first_gate.notify_all();
372 }
373
374 //Upgradable locking
375
376 inline void interprocess_upgradable_mutex::lock_upgradable()
377 {
378 scoped_lock_t lck(m_mut);
379
380 //The upgradable lock must block in the first gate
381 //if an exclusive or upgradable lock has been acquired
382 //or there are too many sharable locks
383 while(this->m_ctrl.exclusive_in || this->m_ctrl.upgradable_in
384 || this->m_ctrl.num_upr_shar == constants::max_readers){
385 this->m_first_gate.wait(lck);
386 }
387
388 //Mark that upgradable lock has been acquired
389 //And add upgradable to the sharable count
390 this->m_ctrl.upgradable_in = 1;
391 ++this->m_ctrl.num_upr_shar;
392 }
393
394 inline bool interprocess_upgradable_mutex::try_lock_upgradable()
395 {
396 scoped_lock_t lck(m_mut, try_to_lock);
397
398 //The upgradable lock must fail
399 //if an exclusive or upgradable lock has been acquired
400 //or there are too many sharable locks
401 if(!lck.owns()
402 || this->m_ctrl.exclusive_in
403 || this->m_ctrl.upgradable_in
404 || this->m_ctrl.num_upr_shar == constants::max_readers){
405 return false;
406 }
407
408 //Mark that upgradable lock has been acquired
409 //And add upgradable to the sharable count
410 this->m_ctrl.upgradable_in = 1;
411 ++this->m_ctrl.num_upr_shar;
412 return true;
413 }
414
415 inline bool interprocess_upgradable_mutex::timed_lock_upgradable
416 (const boost::posix_time::ptime &abs_time)
417 {
418 //Mutexes and condvars handle just fine infinite abs_times
419 //so avoid checking it here
420 scoped_lock_t lck(m_mut, abs_time);
421 if(!lck.owns()) return false;
422
423 //The upgradable lock must block in the first gate
424 //if an exclusive or upgradable lock has been acquired
425 //or there are too many sharable locks
426 while(this->m_ctrl.exclusive_in
427 || this->m_ctrl.upgradable_in
428 || this->m_ctrl.num_upr_shar == constants::max_readers){
429 if(!this->m_first_gate.timed_wait(lck, abs_time)){
430 if((this->m_ctrl.exclusive_in
431 || this->m_ctrl.upgradable_in
432 || this->m_ctrl.num_upr_shar == constants::max_readers)){
433 return false;
434 }
435 break;
436 }
437 }
438
439 //Mark that upgradable lock has been acquired
440 //And add upgradable to the sharable count
441 this->m_ctrl.upgradable_in = 1;
442 ++this->m_ctrl.num_upr_shar;
443 return true;
444 }
445
446 inline void interprocess_upgradable_mutex::unlock_upgradable()
447 {
448 scoped_lock_t lck(m_mut);
449 //Mark that upgradable lock has been acquired
450 //And add upgradable to the sharable count
451 this->m_ctrl.upgradable_in = 0;
452 --this->m_ctrl.num_upr_shar;
453 this->m_first_gate.notify_all();
454 }
455
456 //Sharable locking
457
458 inline void interprocess_upgradable_mutex::lock_sharable()
459 {
460 scoped_lock_t lck(m_mut);
461
462 //The sharable lock must block in the first gate
463 //if an exclusive lock has been acquired
464 //or there are too many sharable locks
465 while(this->m_ctrl.exclusive_in
466 || this->m_ctrl.num_upr_shar == constants::max_readers){
467 this->m_first_gate.wait(lck);
468 }
469
470 //Increment sharable count
471 ++this->m_ctrl.num_upr_shar;
472 }
473
474 inline bool interprocess_upgradable_mutex::try_lock_sharable()
475 {
476 scoped_lock_t lck(m_mut, try_to_lock);
477
478 //The sharable lock must fail
479 //if an exclusive lock has been acquired
480 //or there are too many sharable locks
481 if(!lck.owns()
482 || this->m_ctrl.exclusive_in
483 || this->m_ctrl.num_upr_shar == constants::max_readers){
484 return false;
485 }
486
487 //Increment sharable count
488 ++this->m_ctrl.num_upr_shar;
489 return true;
490 }
491
492 inline bool interprocess_upgradable_mutex::timed_lock_sharable
493 (const boost::posix_time::ptime &abs_time)
494 {
495 //Mutexes and condvars handle just fine infinite abs_times
496 //so avoid checking it here
497 scoped_lock_t lck(m_mut, abs_time);
498 if(!lck.owns()) return false;
499
500 //The sharable lock must block in the first gate
501 //if an exclusive lock has been acquired
502 //or there are too many sharable locks
503 while (this->m_ctrl.exclusive_in
504 || this->m_ctrl.num_upr_shar == constants::max_readers){
505 if(!this->m_first_gate.timed_wait(lck, abs_time)){
506 if(this->m_ctrl.exclusive_in
507 || this->m_ctrl.num_upr_shar == constants::max_readers){
508 return false;
509 }
510 break;
511 }
512 }
513
514 //Increment sharable count
515 ++this->m_ctrl.num_upr_shar;
516 return true;
517 }
518
519 inline void interprocess_upgradable_mutex::unlock_sharable()
520 {
521 scoped_lock_t lck(m_mut);
522 //Decrement sharable count
523 --this->m_ctrl.num_upr_shar;
524 if (this->m_ctrl.num_upr_shar == 0){
525 this->m_second_gate.notify_one();
526 }
527 //Check if there are blocked sharables because of
528 //there were too many sharables
529 else if(this->m_ctrl.num_upr_shar == (constants::max_readers-1)){
530 this->m_first_gate.notify_all();
531 }
532 }
533
534 //Downgrading
535
536 inline void interprocess_upgradable_mutex::unlock_and_lock_upgradable()
537 {
538 scoped_lock_t lck(m_mut);
539 //Unmark it as exclusive
540 this->m_ctrl.exclusive_in = 0;
541 //Mark it as upgradable
542 this->m_ctrl.upgradable_in = 1;
543 //The sharable count should be 0 so increment it
544 this->m_ctrl.num_upr_shar = 1;
545 //Notify readers that they can enter
546 m_first_gate.notify_all();
547 }
548
549 inline void interprocess_upgradable_mutex::unlock_and_lock_sharable()
550 {
551 scoped_lock_t lck(m_mut);
552 //Unmark it as exclusive
553 this->m_ctrl.exclusive_in = 0;
554 //The sharable count should be 0 so increment it
555 this->m_ctrl.num_upr_shar = 1;
556 //Notify readers that they can enter
557 m_first_gate.notify_all();
558 }
559
560 inline void interprocess_upgradable_mutex::unlock_upgradable_and_lock_sharable()
561 {
562 scoped_lock_t lck(m_mut);
563 //Unmark it as upgradable (we don't have to decrement count)
564 this->m_ctrl.upgradable_in = 0;
565 //Notify readers/upgradable that they can enter
566 m_first_gate.notify_all();
567 }
568
569 //Upgrading
570
571 inline void interprocess_upgradable_mutex::unlock_upgradable_and_lock()
572 {
573 scoped_lock_t lck(m_mut);
574 //Simulate unlock_upgradable() without
575 //notifying sharables.
576 this->m_ctrl.upgradable_in = 0;
577 --this->m_ctrl.num_upr_shar;
578 //Execute the second half of exclusive locking
579 this->m_ctrl.exclusive_in = 1;
580
581 //Prepare rollback
582 upgradable_to_exclusive_rollback rollback(m_ctrl);
583
584 while (this->m_ctrl.num_upr_shar){
585 this->m_second_gate.wait(lck);
586 }
587 rollback.release();
588 }
589
590 inline bool interprocess_upgradable_mutex::try_unlock_upgradable_and_lock()
591 {
592 scoped_lock_t lck(m_mut, try_to_lock);
593 //Check if there are no readers
594 if(!lck.owns()
595 || this->m_ctrl.num_upr_shar != 1){
596 return false;
597 }
598 //Now unlock upgradable and mark exclusive
599 this->m_ctrl.upgradable_in = 0;
600 --this->m_ctrl.num_upr_shar;
601 this->m_ctrl.exclusive_in = 1;
602 return true;
603 }
604
605 inline bool interprocess_upgradable_mutex::timed_unlock_upgradable_and_lock
606 (const boost::posix_time::ptime &abs_time)
607 {
608 //Mutexes and condvars handle just fine infinite abs_times
609 //so avoid checking it here
610 scoped_lock_t lck(m_mut, abs_time);
611 if(!lck.owns()) return false;
612
613 //Simulate unlock_upgradable() without
614 //notifying sharables.
615 this->m_ctrl.upgradable_in = 0;
616 --this->m_ctrl.num_upr_shar;
617 //Execute the second half of exclusive locking
618 this->m_ctrl.exclusive_in = 1;
619
620 //Prepare rollback
621 upgradable_to_exclusive_rollback rollback(m_ctrl);
622
623 while (this->m_ctrl.num_upr_shar){
624 if(!this->m_second_gate.timed_wait(lck, abs_time)){
625 if(this->m_ctrl.num_upr_shar){
626 return false;
627 }
628 break;
629 }
630 }
631 rollback.release();
632 return true;
633 }
634
635 inline bool interprocess_upgradable_mutex::try_unlock_sharable_and_lock()
636 {
637 scoped_lock_t lck(m_mut, try_to_lock);
638
639 //If we can't lock or any has there is any exclusive, upgradable
640 //or sharable mark return false;
641 if(!lck.owns()
642 || this->m_ctrl.exclusive_in
643 || this->m_ctrl.upgradable_in
644 || this->m_ctrl.num_upr_shar != 1){
645 return false;
646 }
647 this->m_ctrl.exclusive_in = 1;
648 this->m_ctrl.num_upr_shar = 0;
649 return true;
650 }
651
652 inline bool interprocess_upgradable_mutex::try_unlock_sharable_and_lock_upgradable()
653 {
654 scoped_lock_t lck(m_mut, try_to_lock);
655
656 //The upgradable lock must fail
657 //if an exclusive or upgradable lock has been acquired
658 if(!lck.owns()
659 || this->m_ctrl.exclusive_in
660 || this->m_ctrl.upgradable_in){
661 return false;
662 }
663
664 //Mark that upgradable lock has been acquired
665 this->m_ctrl.upgradable_in = 1;
666 return true;
667 }
668
669 #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
670
671 } //namespace interprocess {
672 } //namespace boost {
673
674
675 #include <boost/interprocess/detail/config_end.hpp>
676
677 #endif //BOOST_INTERPROCESS_UPGRADABLE_MUTEX_HPP