]>
Commit | Line | Data |
---|---|---|
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/recursive_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 | void | |
23 | recursive_mutex::lock() { | |
b32b8144 FG |
24 | while ( true) { |
25 | context * active_ctx = context::active(); | |
26 | // store this fiber in order to be notified later | |
27 | detail::spinlock_lock lk{ wait_queue_splk_ }; | |
28 | if ( active_ctx == owner_) { | |
29 | ++count_; | |
30 | return; | |
f67539c2 TL |
31 | } |
32 | if ( nullptr == owner_) { | |
b32b8144 FG |
33 | owner_ = active_ctx; |
34 | count_ = 1; | |
35 | return; | |
36 | } | |
20effc67 TL |
37 | |
38 | wait_queue_.suspend_and_wait( lk, active_ctx); | |
7c673cae | 39 | } |
7c673cae FG |
40 | } |
41 | ||
42 | bool | |
43 | recursive_mutex::try_lock() noexcept { | |
b32b8144 FG |
44 | context * active_ctx = context::active(); |
45 | detail::spinlock_lock lk{ wait_queue_splk_ }; | |
7c673cae | 46 | if ( nullptr == owner_) { |
b32b8144 | 47 | owner_ = active_ctx; |
7c673cae | 48 | count_ = 1; |
b32b8144 | 49 | } else if ( active_ctx == owner_) { |
7c673cae FG |
50 | ++count_; |
51 | } | |
52 | lk.unlock(); | |
53 | // let other fiber release the lock | |
54 | context::active()->yield(); | |
b32b8144 | 55 | return active_ctx == owner_; |
7c673cae FG |
56 | } |
57 | ||
58 | void | |
59 | recursive_mutex::unlock() { | |
b32b8144 | 60 | context * active_ctx = context::active(); |
7c673cae | 61 | detail::spinlock_lock lk( wait_queue_splk_); |
b32b8144 | 62 | if ( BOOST_UNLIKELY( active_ctx != owner_) ) { |
7c673cae FG |
63 | throw lock_error( |
64 | std::make_error_code( std::errc::operation_not_permitted), | |
65 | "boost fiber: no privilege to perform the operation"); | |
66 | } | |
67 | if ( 0 == --count_) { | |
b32b8144 | 68 | owner_ = nullptr; |
20effc67 | 69 | wait_queue_.notify_one(); |
7c673cae FG |
70 | } |
71 | } | |
72 | ||
73 | }} | |
74 | ||
75 | #ifdef BOOST_HAS_ABI_HEADERS | |
76 | # include BOOST_ABI_SUFFIX | |
77 | #endif |