]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/fiber/src/recursive_timed_mutex.cpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / libs / fiber / src / recursive_timed_mutex.cpp
1
2 // Copyright Oliver Kowalke 2013.
3 // Distributed under the Boost Software License, Version 1.0.
4 // (See accompanying file LICENSE_1_0.txt or copy at
5 // http://www.boost.org/LICENSE_1_0.txt)
6
7 #include "boost/fiber/recursive_timed_mutex.hpp"
8
9 #include <algorithm>
10 #include <functional>
11
12 #include "boost/fiber/exceptions.hpp"
13 #include "boost/fiber/scheduler.hpp"
14
15 #ifdef BOOST_HAS_ABI_HEADERS
16 # include BOOST_ABI_PREFIX
17 #endif
18
19 namespace boost {
20 namespace fibers {
21
22 bool
23 recursive_timed_mutex::try_lock_until_( std::chrono::steady_clock::time_point const& timeout_time) noexcept {
24 while ( true) {
25 if ( std::chrono::steady_clock::now() > timeout_time) {
26 return false;
27 }
28 context * active_ctx = context::active();
29 // store this fiber in order to be notified later
30 detail::spinlock_lock lk{ wait_queue_splk_ };
31 if ( active_ctx == owner_) {
32 ++count_;
33 return true;
34 } else if ( nullptr == owner_) {
35 owner_ = active_ctx;
36 count_ = 1;
37 return true;
38 }
39 BOOST_ASSERT( ! active_ctx->wait_is_linked() );
40 active_ctx->wait_link( wait_queue_);
41 intrusive_ptr_add_ref( active_ctx);
42 active_ctx->twstatus.store( reinterpret_cast< std::intptr_t >( this), std::memory_order_release);
43 // suspend this fiber until notified or timed-out
44 if ( ! active_ctx->wait_until( timeout_time, lk) ) {
45 // remove fiber from wait-queue
46 lk.lock();
47 wait_queue_.remove( * active_ctx);
48 return false;
49 }
50 BOOST_ASSERT( ! active_ctx->wait_is_linked() );
51 }
52 }
53
54 void
55 recursive_timed_mutex::lock() {
56 while ( true) {
57 context * active_ctx = context::active();
58 // store this fiber in order to be notified later
59 detail::spinlock_lock lk{ wait_queue_splk_ };
60 if ( active_ctx == owner_) {
61 ++count_;
62 return;
63 } else if ( nullptr == owner_) {
64 owner_ = active_ctx;
65 count_ = 1;
66 return;
67 }
68 BOOST_ASSERT( ! active_ctx->wait_is_linked() );
69 active_ctx->twstatus.store( static_cast< std::intptr_t >( 0), std::memory_order_release);
70 active_ctx->wait_link( wait_queue_);
71 // suspend this fiber
72 active_ctx->suspend( lk);
73 BOOST_ASSERT( ! active_ctx->wait_is_linked() );
74 }
75 }
76
77 bool
78 recursive_timed_mutex::try_lock() noexcept {
79 context * active_ctx = context::active();
80 detail::spinlock_lock lk{ wait_queue_splk_ };
81 if ( nullptr == owner_) {
82 owner_ = active_ctx;
83 count_ = 1;
84 } else if ( active_ctx == owner_) {
85 ++count_;
86 }
87 lk.unlock();
88 // let other fiber release the lock
89 active_ctx->yield();
90 return active_ctx == owner_;
91 }
92
93 void
94 recursive_timed_mutex::unlock() {
95 context * active_ctx = context::active();
96 detail::spinlock_lock lk{ wait_queue_splk_ };
97 if ( BOOST_UNLIKELY( active_ctx != owner_) ) {
98 throw lock_error{
99 std::make_error_code( std::errc::operation_not_permitted),
100 "boost fiber: no privilege to perform the operation" };
101 }
102 if ( 0 == --count_) {
103 owner_ = nullptr;
104 if ( ! wait_queue_.empty() ) {
105 context * ctx = & wait_queue_.front();
106 wait_queue_.pop_front();
107 std::intptr_t expected = reinterpret_cast< std::intptr_t >( this);
108 if ( ctx->twstatus.compare_exchange_strong( expected, static_cast< std::intptr_t >( -1), std::memory_order_acq_rel) ) {
109 // notify before timeout
110 intrusive_ptr_release( ctx);
111 // notify context
112 active_ctx->schedule( ctx);
113 } else if ( static_cast< std::intptr_t >( 0) == expected) {
114 // no timed-wait op.
115 // notify context
116 active_ctx->schedule( ctx);
117 } else {
118 // timed-wait op.
119 // expected == -1: notify after timeout, same timed-wait op.
120 // expected == <any>: notify after timeout, another timed-wait op. was already started
121 intrusive_ptr_release( ctx);
122 // re-schedule next
123 }
124 }
125 }
126 }
127
128 }}
129
130 #ifdef BOOST_HAS_ABI_HEADERS
131 # include BOOST_ABI_SUFFIX
132 #endif