• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
3 //
4 // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 //
7 // Official repository: https://github.com/boostorg/beast
8 //
9 
10 #ifndef BOOST_BEAST_WEBSOCKET_DETAIL_SOFT_MUTEX_HPP
11 #define BOOST_BEAST_WEBSOCKET_DETAIL_SOFT_MUTEX_HPP
12 
13 #include <boost/assert.hpp>
14 
15 namespace boost {
16 namespace beast {
17 namespace websocket {
18 namespace detail {
19 
20 // used to order reads, writes in websocket streams
21 
22 class soft_mutex
23 {
24     int id_ = 0;
25 
26 public:
27     soft_mutex() = default;
28     soft_mutex(soft_mutex const&) = delete;
29     soft_mutex& operator=(soft_mutex const&) = delete;
30 
soft_mutex(soft_mutex && other)31     soft_mutex(soft_mutex&& other) noexcept
32         : id_(boost::exchange(other.id_, 0))
33     {
34     }
35 
operator =(soft_mutex && other)36     soft_mutex& operator=(soft_mutex&& other) noexcept
37     {
38         id_ = other.id_;
39         other.id_ = 0;
40         return *this;
41     }
42 
43     // VFALCO I'm not too happy that this function is needed
44     void
reset()45     reset()
46     {
47         id_ = 0;
48     }
49 
50     bool
is_locked() const51     is_locked() const noexcept
52     {
53         return id_ != 0;
54     }
55 
56     template<class T>
57     bool
is_locked(T const *) const58     is_locked(T const*) const noexcept
59     {
60         return id_ == T::id;
61     }
62 
63     template<class T>
64     void
lock(T const *)65     lock(T const*)
66     {
67         BOOST_ASSERT(id_ == 0);
68         id_ = T::id;
69     }
70 
71     template<class T>
72     void
unlock(T const *)73     unlock(T const*)
74     {
75         BOOST_ASSERT(id_ == T::id);
76         id_ = 0;
77     }
78 
79     template<class T>
80     bool
try_lock(T const *)81     try_lock(T const*)
82     {
83         // If this assert goes off it means you are attempting to
84         // simultaneously initiate more than one of same asynchronous
85         // operation, which is not allowed. For example, you must wait
86         // for an async_read to complete before performing another
87         // async_read.
88         //
89         BOOST_ASSERT(id_ != T::id);
90         if(id_ != 0)
91             return false;
92         id_ = T::id;
93         return true;
94     }
95 
96     template<class T>
97     bool
try_unlock(T const *)98     try_unlock(T const*) noexcept
99     {
100         if(id_ != T::id)
101             return false;
102         id_ = 0;
103         return true;
104     }
105 };
106 
107 } // detail
108 } // websocket
109 } // beast
110 } // boost
111 
112 #endif
113