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
19namespace boost {
20namespace fibers {
21
22bool
23recursive_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 }
35 if ( nullptr == owner_) {
36 owner_ = active_ctx;
37 count_ = 1;
38 return true;
39 }
40 if ( ! wait_queue_.suspend_and_wait_until( lk, active_ctx, timeout_time)) {
41 return false;
42 }
43 }
44}
45
46void
47recursive_timed_mutex::lock() {
48 while ( true) {
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 ++count_;
54 return;
55 }
56 if ( nullptr == owner_) {
57 owner_ = active_ctx;
58 count_ = 1;
59 return;
60 }
61 wait_queue_.suspend_and_wait( lk, active_ctx);
62 }
63}
64
65bool
66recursive_timed_mutex::try_lock() noexcept {
67 context * active_ctx = context::active();
68 detail::spinlock_lock lk{ wait_queue_splk_ };
69 if ( nullptr == owner_) {
70 owner_ = active_ctx;
71 count_ = 1;
72 } else if ( active_ctx == owner_) {
73 ++count_;
74 }
75 lk.unlock();
76 // let other fiber release the lock
77 active_ctx->yield();
78 return active_ctx == owner_;
79}
80
81void
82recursive_timed_mutex::unlock() {
83 context * active_ctx = context::active();
84 detail::spinlock_lock lk{ wait_queue_splk_ };
85 if ( BOOST_UNLIKELY( active_ctx != owner_) ) {
86 throw lock_error{
87 std::make_error_code( e: std::errc::operation_not_permitted),
88 "boost fiber: no privilege to perform the operation" };
89 }
90 if ( 0 == --count_) {
91 owner_ = nullptr;
92 wait_queue_.notify_one();
93 }
94}
95
96}}
97
98#ifdef BOOST_HAS_ABI_HEADERS
99# include BOOST_ABI_SUFFIX
100#endif
101

source code of boost/libs/fiber/src/recursive_timed_mutex.cpp