• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
lock()24 mutex::lock() {
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         }
34         if ( nullptr == owner_) {
35             owner_ = active_ctx;
36             return;
37         }
38         BOOST_ASSERT( ! active_ctx->wait_is_linked() );
39         active_ctx->wait_link( wait_queue_);
40         // suspend this fiber
41         active_ctx->suspend( lk);
42         BOOST_ASSERT( ! active_ctx->wait_is_linked() );
43     }
44 }
45 
46 bool
try_lock()47 mutex::try_lock() {
48     context * active_ctx = context::active();
49     detail::spinlock_lock lk{ wait_queue_splk_ };
50     if ( BOOST_UNLIKELY( active_ctx == owner_) ) {
51         throw lock_error{
52                 std::make_error_code( std::errc::resource_deadlock_would_occur),
53                 "boost fiber: a deadlock is detected" };
54     }
55     if ( nullptr == owner_) {
56         owner_ = active_ctx;
57     }
58     lk.unlock();
59     // let other fiber release the lock
60     active_ctx->yield();
61     return active_ctx == owner_;
62 }
63 
64 void
unlock()65 mutex::unlock() {
66     context * active_ctx = context::active();
67     detail::spinlock_lock lk{ wait_queue_splk_ };
68     if ( BOOST_UNLIKELY( active_ctx != owner_) ) {
69         throw lock_error{
70                 std::make_error_code( std::errc::operation_not_permitted),
71                 "boost fiber: no  privilege to perform the operation" };
72     }
73     owner_ = nullptr;
74     if ( ! wait_queue_.empty() ) {
75         context * ctx = & wait_queue_.front();
76         wait_queue_.pop_front();
77         active_ctx->schedule( ctx);
78     }
79 }
80 
81 }}
82 
83 #ifdef BOOST_HAS_ABI_HEADERS
84 #  include BOOST_ABI_SUFFIX
85 #endif
86