Imported Upstream version 1.64.0
[platform/upstream/boost.git] / 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     if ( std::chrono::steady_clock::now() > timeout_time) {
25         return false;
26     }
27     context * active_ctx = context::active();
28     // store this fiber in order to be notified later
29     detail::spinlock_lock lk{ wait_queue_splk_ };
30     if ( nullptr == owner_) {
31         owner_ = active_ctx;
32         return true;
33     }
34     BOOST_ASSERT( ! active_ctx->wait_is_linked() );
35     active_ctx->wait_link( wait_queue_);
36     // suspend this fiber until notified or timed-out
37     if ( ! active_ctx->wait_until( timeout_time, lk) ) {
38         // remove fiber from wait-queue 
39         lk.lock();
40         wait_queue_.remove( * active_ctx);
41         return false;
42     }
43     BOOST_ASSERT( ! active_ctx->wait_is_linked() );
44     return true;
45 }
46
47 void
48 timed_mutex::lock() {
49     context * active_ctx = context::active();
50     // store this fiber in order to be notified later
51     detail::spinlock_lock lk{ wait_queue_splk_ };
52     if ( active_ctx == owner_) {
53         throw lock_error{
54                 std::make_error_code( std::errc::resource_deadlock_would_occur),
55                 "boost fiber: a deadlock is detected" };
56     } else if ( nullptr == owner_) {
57         owner_ = active_ctx;
58         return;
59     }
60     BOOST_ASSERT( ! active_ctx->wait_is_linked() );
61     active_ctx->wait_link( wait_queue_);
62     // suspend this fiber
63     active_ctx->suspend( lk);
64     BOOST_ASSERT( ! active_ctx->wait_is_linked() );
65 }
66
67 bool
68 timed_mutex::try_lock() {
69     context * active_ctx = context::active();
70     detail::spinlock_lock lk{ wait_queue_splk_ };
71     if ( active_ctx == owner_) {
72         throw lock_error{
73                 std::make_error_code( std::errc::resource_deadlock_would_occur),
74                 "boost fiber: a deadlock is detected" };
75     } else if ( nullptr == owner_) {
76         owner_ = active_ctx;
77     }
78     lk.unlock();
79     // let other fiber release the lock
80     active_ctx->yield();
81     return active_ctx == owner_;
82 }
83
84 void
85 timed_mutex::unlock() {
86     context * active_ctx = context::active();
87     detail::spinlock_lock lk{ wait_queue_splk_ };
88     if ( active_ctx != owner_) {
89         throw lock_error{
90                 std::make_error_code( std::errc::operation_not_permitted),
91                 "boost fiber: no  privilege to perform the operation" };
92     }
93     if ( ! wait_queue_.empty() ) {
94         context * ctx = & wait_queue_.front();
95         wait_queue_.pop_front();
96         owner_ = ctx;
97         active_ctx->schedule( ctx);
98     } else {
99         owner_ = nullptr;
100         return;
101     }
102 }
103
104 }}
105
106 #ifdef BOOST_HAS_ABI_HEADERS
107 #  include BOOST_ABI_SUFFIX
108 #endif