]>
git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/fiber/src/recursive_timed_mutex.cpp
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)
7 #include "boost/fiber/recursive_timed_mutex.hpp"
12 #include "boost/fiber/exceptions.hpp"
13 #include "boost/fiber/scheduler.hpp"
15 #ifdef BOOST_HAS_ABI_HEADERS
16 # include BOOST_ABI_PREFIX
23 recursive_timed_mutex::try_lock_until_( std::chrono::steady_clock::time_point
const& timeout_time
) noexcept
{
25 if ( std::chrono::steady_clock::now() > timeout_time
) {
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_
) {
34 } else if ( nullptr == owner_
) {
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
47 wait_queue_
.remove( * active_ctx
);
50 BOOST_ASSERT( ! active_ctx
->wait_is_linked() );
55 recursive_timed_mutex::lock() {
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_
) {
63 } else if ( nullptr == owner_
) {
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_
);
72 active_ctx
->suspend( lk
);
73 BOOST_ASSERT( ! active_ctx
->wait_is_linked() );
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_
) {
84 } else if ( active_ctx
== owner_
) {
88 // let other fiber release the lock
90 return active_ctx
== owner_
;
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_
) ) {
99 std::make_error_code( std::errc::operation_not_permitted
),
100 "boost fiber: no privilege to perform the operation" };
102 if ( 0 == --count_
) {
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
);
112 active_ctx
->schedule( ctx
);
113 } else if ( static_cast< std::intptr_t >( 0) == expected
) {
116 active_ctx
->schedule( ctx
);
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
);
130 #ifdef BOOST_HAS_ABI_HEADERS
131 # include BOOST_ABI_SUFFIX