1#ifndef BOOST_COMPAT_SHARED_LOCK_HPP_INCLUDED
2#define BOOST_COMPAT_SHARED_LOCK_HPP_INCLUDED
3
4// Copyright 2023 Christian Mazakas.
5// Distributed under the Boost Software License, Version 1.0.
6// https://www.boost.org/LICENSE_1_0.txt
7
8#include <boost/compat/detail/throw_system_error.hpp>
9
10#include <memory> // std::addressof
11#include <mutex> // std::defer_lock_t
12#include <system_error> // std::errc
13
14namespace boost {
15namespace compat {
16
17template <class Mutex>
18class shared_lock;
19
20template <class Mutex>
21void swap( shared_lock<Mutex>& x, shared_lock<Mutex>& y ) noexcept;
22
23template <class Mutex>
24class shared_lock {
25private:
26 Mutex* pm_ = nullptr;
27 bool owns_ = false;
28
29public:
30 using mutex_type = Mutex;
31
32 shared_lock() noexcept = default;
33
34 explicit shared_lock( mutex_type& m ) : pm_( std::addressof( m ) ) { lock(); }
35
36 shared_lock( mutex_type& m, std::defer_lock_t ) noexcept
37 : pm_( std::addressof( m ) ) {}
38
39 shared_lock( mutex_type& m, std::try_to_lock_t )
40 : pm_( std::addressof( m ) ) {
41 try_lock();
42 }
43
44 shared_lock( mutex_type& m, std::adopt_lock_t )
45 : pm_( std::addressof( m ) ), owns_{ true } {}
46
47 ~shared_lock() {
48 if ( owns_ ) {
49 unlock();
50 }
51 }
52
53 shared_lock( const shared_lock& ) = delete;
54 shared_lock& operator=( const shared_lock& ) = delete;
55
56 shared_lock( shared_lock&& u ) noexcept {
57 pm_ = u.pm_;
58 owns_ = u.owns_;
59
60 u.pm_ = nullptr;
61 u.owns_ = false;
62 }
63
64 shared_lock& operator=( shared_lock&& u ) noexcept {
65 shared_lock( std::move( u ) ).swap( *this );
66 return *this;
67 }
68
69 void lock() {
70 if ( !pm_ ) {
71 detail::throw_system_error( e: std::errc::operation_not_permitted );
72 }
73
74 if ( owns_lock() ) {
75 detail::throw_system_error( e: std::errc::resource_deadlock_would_occur );
76 }
77
78 pm_->lock_shared();
79 owns_ = true;
80 }
81
82 bool try_lock() {
83 if ( !pm_ ) {
84 detail::throw_system_error( e: std::errc::operation_not_permitted );
85 }
86
87 if ( owns_lock() ) {
88 detail::throw_system_error( e: std::errc::resource_deadlock_would_occur );
89 }
90
91 bool b = pm_->try_lock_shared();
92 owns_ = b;
93 return b;
94 }
95
96 void unlock() {
97 if ( !pm_ || !owns_ ) {
98 detail::throw_system_error( e: std::errc::operation_not_permitted );
99 }
100
101 pm_->unlock_shared();
102 owns_ = false;
103 }
104
105 void swap( shared_lock& u ) noexcept {
106 std::swap( pm_, u.pm_ );
107 std::swap( owns_, u.owns_ );
108 }
109
110 mutex_type* release() noexcept {
111 mutex_type* pm = pm_;
112 pm_ = nullptr;
113 owns_ = false;
114 return pm;
115 }
116
117 mutex_type* mutex() const noexcept { return pm_; }
118
119 bool owns_lock() const noexcept { return owns_; }
120 explicit operator bool() const noexcept { return owns_; }
121};
122
123template <class Mutex>
124void swap( shared_lock<Mutex>& x, shared_lock<Mutex>& y ) noexcept {
125 x.swap( y );
126}
127
128} // namespace compat
129} // namespace boost
130
131#endif // BOOST_COMPAT_SHARED_LOCK_HPP_INCLUDED
132

source code of boost/libs/compat/include/boost/compat/shared_lock.hpp