]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/fiber/src/timed_mutex.cpp
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / boost / libs / fiber / src / 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/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 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 ( 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 active_ctx->twstatus.store( reinterpret_cast< std::intptr_t >( this), std::memory_order_release);
38 // suspend this fiber until notified or timed-out
39 if ( ! active_ctx->wait_until( timeout_time, lk) ) {
40 // remove fiber from wait-queue
41 lk.lock();
42 wait_queue_.remove( * active_ctx);
43 return false;
44 }
45 BOOST_ASSERT( ! active_ctx->wait_is_linked() );
46 }
47 }
48
49 void
50 timed_mutex::lock() {
51 while ( true) {
52 context * active_ctx = context::active();
53 // store this fiber in order to be notified later
54 detail::spinlock_lock lk{ wait_queue_splk_ };
55 if ( BOOST_UNLIKELY( active_ctx == owner_) ) {
56 throw lock_error{
57 std::make_error_code( std::errc::resource_deadlock_would_occur),
58 "boost fiber: a deadlock is detected" };
59 }
60 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() );
70 }
71 }
72
73 bool
74 timed_mutex::try_lock() {
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{
79 std::make_error_code( std::errc::resource_deadlock_would_occur),
80 "boost fiber: a deadlock is detected" };
81 }
82 if ( nullptr == owner_) {
83 owner_ = active_ctx;
84 }
85 lk.unlock();
86 // let other fiber release the lock
87 active_ctx->yield();
88 return active_ctx == owner_;
89 }
90
91 void
92 timed_mutex::unlock() {
93 context * active_ctx = context::active();
94 detail::spinlock_lock lk{ wait_queue_splk_ };
95 if ( BOOST_UNLIKELY( active_ctx != owner_) ) {
96 throw lock_error{
97 std::make_error_code( std::errc::operation_not_permitted),
98 "boost fiber: no privilege to perform the operation" };
99 }
100 owner_ = nullptr;
101 if ( ! wait_queue_.empty() ) {
102 context * ctx = & wait_queue_.front();
103 wait_queue_.pop_front();
104 auto expected = reinterpret_cast< std::intptr_t >( this);
105 if ( ctx->twstatus.compare_exchange_strong( expected, static_cast< std::intptr_t >( -1), std::memory_order_acq_rel) ) {
106 // notify context
107 active_ctx->schedule( ctx);
108 } else if ( static_cast< std::intptr_t >( 0) == expected) {
109 // no timed-wait op.
110 // notify context
111 active_ctx->schedule( ctx);
112 }
113 }
114 }
115
116 }}
117
118 #ifdef BOOST_HAS_ABI_HEADERS
119 # include BOOST_ABI_SUFFIX
120 #endif