]>
git.proxmox.com Git - ceph.git/blob - ceph/src/crimson/common/tri_mutex.h
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:nil -*-
2 // vim: ts=8 sw=2 smarttab
6 #include <seastar/core/future.hh>
7 #include <seastar/core/circular_buffer.hh>
11 seastar::future
<> lock();
17 seastar::future
<> lock();
23 seastar::future
<> lock();
27 // promote from read to excl
28 class excl_lock_from_read
{
30 seastar::future
<> lock();
34 // promote from write to excl
35 class excl_lock_from_write
{
37 seastar::future
<> lock();
41 // promote from excl to excl
42 class excl_lock_from_excl
{
44 seastar::future
<> lock();
48 /// shared/exclusive mutual exclusion
50 /// this lock design uses reader and writer is entirely and completely
51 /// independent of the conventional reader/writer lock usage. Here, what we
52 /// mean is that we can pipeline reads, and we can pipeline writes, but we
53 /// cannot allow a read while writes are in progress or a write while reads are
54 /// in progress. Any rmw operation is therefore exclusive.
56 /// tri_mutex is based on seastar::shared_mutex, but instead of two kinds of
57 /// waiters, tri_mutex keeps track of three kinds of lock users:
61 class tri_mutex
: private read_lock
,
69 tri_mutex() = default;
72 read_lock
& for_read() {
75 write_lock
& for_write() {
78 excl_lock
& for_excl() {
81 excl_lock_from_read
& excl_from_read() {
84 excl_lock_from_write
& excl_from_write() {
87 excl_lock_from_excl
& excl_from_excl() {
92 seastar::future
<> lock_for_read();
93 bool try_lock_for_read() noexcept
;
94 void unlock_for_read();
95 void promote_from_read();
96 void demote_to_read();
97 unsigned get_readers() const {
101 // for shared writers
102 seastar::future
<> lock_for_write(bool greedy
);
103 bool try_lock_for_write(bool greedy
) noexcept
;
104 void unlock_for_write();
105 void promote_from_write();
106 void demote_to_write();
107 unsigned get_writers() const {
111 // for exclusive users
112 seastar::future
<> lock_for_excl();
113 bool try_lock_for_excl() noexcept
;
114 void unlock_for_excl();
115 bool is_excl_acquired() const {
116 return exclusively_used
;
119 bool is_acquired() const;
121 /// pass the provided exception to any waiting waiters
122 template<typename Exception
>
123 void abort(Exception ex
) {
124 while (!waiters
.empty()) {
125 auto& waiter
= waiters
.front();
126 waiter
.pr
.set_exception(std::make_exception_ptr(ex
));
133 unsigned readers
= 0;
134 unsigned writers
= 0;
135 bool exclusively_used
= false;
136 enum class type_t
: uint8_t {
143 waiter_t(seastar::promise
<>&& pr
, type_t type
)
144 : pr(std::move(pr
)), type(type
)
146 seastar::promise
<> pr
;
149 seastar::circular_buffer
<waiter_t
> waiters
;
150 friend class read_lock
;
151 friend class write_lock
;
152 friend class excl_lock
;
153 friend class excl_lock_from_read
;
154 friend class excl_lock_from_write
;
155 friend class excl_lock_from_excl
;