]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/fiber/src/timed_mutex.cpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / libs / fiber / src / timed_mutex.cpp
CommitLineData
7c673cae
FG
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/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
19namespace boost {
20namespace fibers {
21
22bool
23timed_mutex::try_lock_until_( std::chrono::steady_clock::time_point const& timeout_time) noexcept {
b32b8144
FG
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 ( nullptr == owner_) {
32 owner_ = active_ctx;
33 return true;
34 }
35 BOOST_ASSERT( ! active_ctx->wait_is_linked() );
36 active_ctx->wait_link( wait_queue_);
37 intrusive_ptr_add_ref( active_ctx);
38 active_ctx->twstatus.store( reinterpret_cast< std::intptr_t >( this), std::memory_order_release);
39 // suspend this fiber until notified or timed-out
40 if ( ! active_ctx->wait_until( timeout_time, lk) ) {
41 // remove fiber from wait-queue
42 lk.lock();
43 wait_queue_.remove( * active_ctx);
44 return false;
45 }
46 BOOST_ASSERT( ! active_ctx->wait_is_linked() );
7c673cae 47 }
7c673cae
FG
48}
49
50void
51timed_mutex::lock() {
b32b8144
FG
52 while ( true) {
53 context * active_ctx = context::active();
54 // store this fiber in order to be notified later
55 detail::spinlock_lock lk{ wait_queue_splk_ };
56 if ( BOOST_UNLIKELY( active_ctx == owner_) ) {
57 throw lock_error{
58 std::make_error_code( std::errc::resource_deadlock_would_occur),
59 "boost fiber: a deadlock is detected" };
60 } else if ( nullptr == owner_) {
61 owner_ = active_ctx;
62 return;
63 }
64 BOOST_ASSERT( ! active_ctx->wait_is_linked() );
65 active_ctx->wait_link( wait_queue_);
66 active_ctx->twstatus.store( static_cast< std::intptr_t >( 0), std::memory_order_release);
67 // suspend this fiber
68 active_ctx->suspend( lk);
69 BOOST_ASSERT( ! active_ctx->wait_is_linked() );
7c673cae 70 }
7c673cae
FG
71}
72
73bool
74timed_mutex::try_lock() {
b32b8144
FG
75 context * active_ctx = context::active();
76 detail::spinlock_lock lk{ wait_queue_splk_ };
77 if ( BOOST_UNLIKELY( active_ctx == owner_) ) {
78 throw lock_error{
7c673cae 79 std::make_error_code( std::errc::resource_deadlock_would_occur),
b32b8144 80 "boost fiber: a deadlock is detected" };
7c673cae 81 } else if ( nullptr == owner_) {
b32b8144 82 owner_ = active_ctx;
7c673cae
FG
83 }
84 lk.unlock();
85 // let other fiber release the lock
b32b8144
FG
86 active_ctx->yield();
87 return active_ctx == owner_;
7c673cae
FG
88}
89
90void
91timed_mutex::unlock() {
b32b8144
FG
92 context * active_ctx = context::active();
93 detail::spinlock_lock lk{ wait_queue_splk_ };
94 if ( BOOST_UNLIKELY( active_ctx != owner_) ) {
95 throw lock_error{
7c673cae 96 std::make_error_code( std::errc::operation_not_permitted),
b32b8144 97 "boost fiber: no privilege to perform the operation" };
7c673cae 98 }
b32b8144 99 owner_ = nullptr;
7c673cae
FG
100 if ( ! wait_queue_.empty() ) {
101 context * ctx = & wait_queue_.front();
102 wait_queue_.pop_front();
b32b8144
FG
103 std::intptr_t expected = reinterpret_cast< std::intptr_t >( this);
104 if ( ctx->twstatus.compare_exchange_strong( expected, static_cast< std::intptr_t >( -1), std::memory_order_acq_rel) ) {
105 // notify before timeout
106 intrusive_ptr_release( ctx);
107 // notify context
108 active_ctx->schedule( ctx);
109 } else if ( static_cast< std::intptr_t >( 0) == expected) {
110 // no timed-wait op.
111 // notify context
112 active_ctx->schedule( ctx);
113 } else {
114 // timed-wait op.
115 // expected == -1: notify after timeout, same timed-wait op.
116 // expected == <any>: notify after timeout, another timed-wait op. was already started
117 intrusive_ptr_release( ctx);
118 // re-schedule next
119 }
7c673cae
FG
120 }
121}
122
123}}
124
125#ifdef BOOST_HAS_ABI_HEADERS
126# include BOOST_ABI_SUFFIX
127#endif