Seastar
High performance C++ framework for concurrent servers
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Modules Pages
rwlock.hh
1/*
2* This file is open source software, licensed to you under the terms
3* of the Apache License, Version 2.0 (the "License"). See the NOTICE file
4* distributed with this work for additional information regarding copyright
5* ownership. You may not use this file except in compliance with the License.
6*
7* You may obtain a copy of the License at
8*
9* http://www.apache.org/licenses/LICENSE-2.0
10*
11* Unless required by applicable law or agreed to in writing,
12* software distributed under the License is distributed on an
13* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14* KIND, either express or implied. See the License for the
15* specific language governing permissions and limitations
16* under the License.
17*/
18/*
19 * Copyright (C) 2015 Cloudius Systems, Ltd.
20 */
21
22#pragma once
23
24#ifndef SEASTAR_MODULE
25#include <cstddef>
26#endif
27#include <seastar/core/semaphore.hh>
28#include <seastar/util/assert.hh>
29#include <seastar/util/modules.hh>
30
31namespace seastar {
32
34// lock / unlock semantics for rwlock, so it can be used with with_lock()
35SEASTAR_MODULE_EXPORT
36template<typename Clock>
37class basic_rwlock;
38
39template<typename Clock = typename timer<>::clock>
40class rwlock_for_read {
41public:
42 future<> lock() {
43 return static_cast<basic_rwlock<Clock>*>(this)->read_lock();
44 }
45 void unlock() {
46 static_cast<basic_rwlock<Clock>*>(this)->read_unlock();
47 }
48 friend class basic_rwlock<Clock>;
49};
50
51template<typename Clock = typename timer<>::clock>
52class rwlock_for_write {
53public:
54 future<> lock() {
55 return static_cast<basic_rwlock<Clock>*>(this)->write_lock();
56 }
57 void unlock() {
58 static_cast<basic_rwlock<Clock>*>(this)->write_unlock();
59 }
60 friend class basic_rwlock<Clock>;
61};
63
64
67
74SEASTAR_MODULE_EXPORT
75template<typename Clock = typename timer<>::clock>
76class basic_rwlock : private rwlock_for_read<Clock>, rwlock_for_write<Clock> {
78
79 static constexpr size_t max_ops = semaphore_type::max_counter();
80
81 semaphore_type _sem;
82public:
84 : _sem(max_ops) {
85 }
86
90 rwlock_for_read<Clock>& for_read() {
91 return *this;
92 }
93
97 rwlock_for_write<Clock>& for_write() {
98 return *this;
99 }
100
104 future<> read_lock(typename semaphore_type::time_point timeout = semaphore_type::time_point::max()) {
105 return _sem.wait(timeout);
106 }
107
109 return _sem.wait(as);
110 }
111
115 void read_unlock() {
116 SEASTAR_ASSERT(_sem.current() < max_ops);
117 _sem.signal();
118 }
119
124 future<> write_lock(typename semaphore_type::time_point timeout = semaphore_type::time_point::max()) {
125 return _sem.wait(timeout, max_ops);
126 }
127
129 return _sem.wait(as, max_ops);
130 }
131
136 SEASTAR_ASSERT(_sem.current() == 0);
137 _sem.signal(max_ops);
138 }
139
142 return _sem.try_wait();
143 }
144
147 return _sem.try_wait(max_ops);
148 }
149
151
163 future<holder> hold_read_lock(typename semaphore_type::time_point timeout = semaphore_type::time_point::max()) {
164 return get_units(_sem, 1, timeout);
165 }
166
168 return get_units(_sem, 1, as);
169 }
170
173 std::optional<holder> try_hold_read_lock() noexcept {
174 return try_get_units(_sem, 1);
175 }
176
188 future<holder> hold_write_lock(typename semaphore_type::time_point timeout = semaphore_type::time_point::max()) {
189 return get_units(_sem, max_ops, timeout);
190 }
191
193 return get_units(_sem, max_ops, as);
194 }
195
198 std::optional<holder> try_hold_write_lock() noexcept {
199 return try_get_units(_sem, max_ops);
200 }
201
203 bool locked() const {
204 return _sem.available_units() != max_ops;
205 }
206
207 friend class rwlock_for_read<Clock>;
208 friend class rwlock_for_write<Clock>;
209};
210
211SEASTAR_MODULE_EXPORT
212using rwlock = basic_rwlock<>;
213
215
216}
Definition: abort_source.hh:59
Definition: rwlock.hh:76
future read_lock(typename semaphore_type::time_point timeout=semaphore_type::time_point::max())
Definition: rwlock.hh:104
std::optional< holder > try_hold_write_lock() noexcept
Definition: rwlock.hh:198
void read_unlock()
Definition: rwlock.hh:115
std::optional< holder > try_hold_read_lock() noexcept
Definition: rwlock.hh:173
future write_lock(typename semaphore_type::time_point timeout=semaphore_type::time_point::max())
Definition: rwlock.hh:124
bool try_read_lock()
Tries to acquire the lock in read mode iff this can be done without waiting.
Definition: rwlock.hh:141
bool try_write_lock()
Tries to acquire the lock in write mode iff this can be done without waiting.
Definition: rwlock.hh:146
rwlock_for_write< Clock > & for_write()
Definition: rwlock.hh:97
rwlock_for_read< Clock > & for_read()
Definition: rwlock.hh:90
future< holder > hold_read_lock(typename semaphore_type::time_point timeout=semaphore_type::time_point::max())
Definition: rwlock.hh:163
bool locked() const
Checks if any read or write locks are currently held.
Definition: rwlock.hh:203
future< holder > hold_write_lock(typename semaphore_type::time_point timeout=semaphore_type::time_point::max())
Definition: rwlock.hh:188
void write_unlock()
Definition: rwlock.hh:135
Counted resource guard.
Definition: semaphore.hh:154
static constexpr size_t max_counter() noexcept
Returns the maximum number of units the semaphore counter can hold.
Definition: semaphore.hh:239
size_t current() const noexcept
Definition: semaphore.hh:460
future wait(size_t nr=1) noexcept
Definition: semaphore.hh:307
ssize_t available_units() const noexcept
Definition: semaphore.hh:466
bool try_wait(size_t nr=1) noexcept
Definition: semaphore.hh:448
void signal(size_t nr=1) noexcept
Definition: semaphore.hh:410
A representation of a possibly not-yet-computed value.
Definition: future.hh:1197
Definition: semaphore.hh:525
Seastar API namespace.
Definition: abort_on_ebadf.hh:26