]>
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" | |
15 | ||
16 | #ifdef BOOST_HAS_ABI_HEADERS | |
17 | # include BOOST_ABI_PREFIX | |
18 | #endif | |
19 | ||
20 | namespace boost { | |
21 | namespace fibers { | |
22 | ||
23 | void | |
24 | mutex::lock() { | |
b32b8144 FG |
25 | while ( true) { |
26 | context * active_ctx = context::active(); | |
27 | // store this fiber in order to be notified later | |
28 | detail::spinlock_lock lk{ wait_queue_splk_ }; | |
29 | if ( BOOST_UNLIKELY( active_ctx == owner_) ) { | |
30 | throw lock_error{ | |
31 | std::make_error_code( std::errc::resource_deadlock_would_occur), | |
32 | "boost fiber: a deadlock is detected" }; | |
33 | } else if ( nullptr == owner_) { | |
34 | owner_ = active_ctx; | |
35 | return; | |
36 | } | |
37 | BOOST_ASSERT( ! active_ctx->wait_is_linked() ); | |
38 | active_ctx->wait_link( wait_queue_); | |
39 | // suspend this fiber | |
40 | active_ctx->suspend( lk); | |
41 | BOOST_ASSERT( ! active_ctx->wait_is_linked() ); | |
7c673cae | 42 | } |
7c673cae FG |
43 | } |
44 | ||
45 | bool | |
46 | mutex::try_lock() { | |
b32b8144 FG |
47 | context * active_ctx = context::active(); |
48 | detail::spinlock_lock lk{ wait_queue_splk_ }; | |
49 | if ( BOOST_UNLIKELY( active_ctx == owner_) ) { | |
50 | throw lock_error{ | |
7c673cae | 51 | std::make_error_code( std::errc::resource_deadlock_would_occur), |
b32b8144 | 52 | "boost fiber: a deadlock is detected" }; |
7c673cae | 53 | } else 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; |
7c673cae FG |
72 | if ( ! wait_queue_.empty() ) { |
73 | context * ctx = & wait_queue_.front(); | |
74 | wait_queue_.pop_front(); | |
b32b8144 | 75 | active_ctx->schedule( ctx); |
7c673cae FG |
76 | } |
77 | } | |
78 | ||
79 | }} | |
80 | ||
81 | #ifdef BOOST_HAS_ABI_HEADERS | |
82 | # include BOOST_ABI_SUFFIX | |
83 | #endif |