• 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/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
lock()23 recursive_mutex::lock() {
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;
31         }
32         if ( nullptr == owner_) {
33             owner_ = active_ctx;
34             count_ = 1;
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() );
42     }
43 }
44 
45 bool
try_lock()46 recursive_mutex::try_lock() noexcept {
47     context * active_ctx = context::active();
48     detail::spinlock_lock lk{ wait_queue_splk_ };
49     if ( nullptr == owner_) {
50         owner_ = active_ctx;
51         count_ = 1;
52     } else if ( active_ctx == owner_) {
53         ++count_;
54     }
55     lk.unlock();
56     // let other fiber release the lock
57     context::active()->yield();
58     return active_ctx == owner_;
59 }
60 
61 void
unlock()62 recursive_mutex::unlock() {
63     context * active_ctx = context::active();
64     detail::spinlock_lock lk( wait_queue_splk_);
65     if ( BOOST_UNLIKELY( active_ctx != owner_) ) {
66         throw lock_error(
67                 std::make_error_code( std::errc::operation_not_permitted),
68                 "boost fiber: no  privilege to perform the operation");
69     }
70     if ( 0 == --count_) {
71         owner_ = nullptr;
72         if ( ! wait_queue_.empty() ) {
73             context * ctx = & wait_queue_.front();
74             wait_queue_.pop_front();
75             active_ctx->schedule( ctx);
76         }
77     }
78 }
79 
80 }}
81 
82 #ifdef BOOST_HAS_ABI_HEADERS
83 #  include BOOST_ABI_SUFFIX
84 #endif
85