]>
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/mutex.hpp" | |
8 | ||
9 | #include <algorithm> | |
10 | #include <functional> | |
11 | #include <system_error> | |
12 | ||
13 | #include "boost/fiber/exceptions.hpp" | |
14 | #include "boost/fiber/scheduler.hpp" | |
20effc67 | 15 | #include "boost/fiber/waker.hpp" |
7c673cae FG |
16 | |
17 | #ifdef BOOST_HAS_ABI_HEADERS | |
18 | # include BOOST_ABI_PREFIX | |
19 | #endif | |
20 | ||
21 | namespace boost { | |
22 | namespace fibers { | |
23 | ||
24 | void | |
25 | mutex::lock() { | |
b32b8144 FG |
26 | while ( true) { |
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 ( BOOST_UNLIKELY( active_ctx == owner_) ) { | |
31 | throw lock_error{ | |
32 | std::make_error_code( std::errc::resource_deadlock_would_occur), | |
33 | "boost fiber: a deadlock is detected" }; | |
f67539c2 TL |
34 | } |
35 | if ( nullptr == owner_) { | |
b32b8144 FG |
36 | owner_ = active_ctx; |
37 | return; | |
38 | } | |
20effc67 TL |
39 | |
40 | wait_queue_.suspend_and_wait( lk, active_ctx); | |
7c673cae | 41 | } |
7c673cae FG |
42 | } |
43 | ||
44 | bool | |
45 | mutex::try_lock() { | |
b32b8144 FG |
46 | context * active_ctx = context::active(); |
47 | detail::spinlock_lock lk{ wait_queue_splk_ }; | |
48 | if ( BOOST_UNLIKELY( active_ctx == owner_) ) { | |
49 | throw lock_error{ | |
7c673cae | 50 | std::make_error_code( std::errc::resource_deadlock_would_occur), |
b32b8144 | 51 | "boost fiber: a deadlock is detected" }; |
f67539c2 TL |
52 | } |
53 | if ( nullptr == owner_) { | |
b32b8144 | 54 | owner_ = active_ctx; |
7c673cae FG |
55 | } |
56 | lk.unlock(); | |
57 | // let other fiber release the lock | |
b32b8144 FG |
58 | active_ctx->yield(); |
59 | return active_ctx == owner_; | |
7c673cae FG |
60 | } |
61 | ||
62 | void | |
63 | mutex::unlock() { | |
b32b8144 FG |
64 | context * active_ctx = context::active(); |
65 | detail::spinlock_lock lk{ wait_queue_splk_ }; | |
66 | if ( BOOST_UNLIKELY( active_ctx != owner_) ) { | |
67 | throw lock_error{ | |
7c673cae | 68 | std::make_error_code( std::errc::operation_not_permitted), |
b32b8144 | 69 | "boost fiber: no privilege to perform the operation" }; |
7c673cae | 70 | } |
b32b8144 | 71 | owner_ = nullptr; |
20effc67 TL |
72 | |
73 | wait_queue_.notify_one(); | |
7c673cae FG |
74 | } |
75 | ||
76 | }} | |
77 | ||
78 | #ifdef BOOST_HAS_ABI_HEADERS | |
79 | # include BOOST_ABI_SUFFIX | |
80 | #endif |