Seastar
High performance C++ framework for concurrent servers
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/modules.hh>
29
30namespace seastar {
31
33// lock / unlock semantics for rwlock, so it can be used with with_lock()
34SEASTAR_MODULE_EXPORT
35template<typename Clock>
36class basic_rwlock;
37
38template<typename Clock = typename timer<>::clock>
39class rwlock_for_read {
40public:
41 future<> lock() {
42 return static_cast<basic_rwlock<Clock>*>(this)->read_lock();
43 }
44 void unlock() {
45 static_cast<basic_rwlock<Clock>*>(this)->read_unlock();
46 }
47 friend class basic_rwlock<Clock>;
48};
49
50template<typename Clock = typename timer<>::clock>
51class rwlock_for_write {
52public:
53 future<> lock() {
54 return static_cast<basic_rwlock<Clock>*>(this)->write_lock();
55 }
56 void unlock() {
57 static_cast<basic_rwlock<Clock>*>(this)->write_unlock();
58 }
59 friend class basic_rwlock<Clock>;
60};
62
63
66
73SEASTAR_MODULE_EXPORT
74template<typename Clock = typename timer<>::clock>
75class basic_rwlock : private rwlock_for_read<Clock>, rwlock_for_write<Clock> {
77
78 static constexpr size_t max_ops = semaphore_type::max_counter();
79
80 semaphore_type _sem;
81public:
83 : _sem(max_ops) {
84 }
85
89 rwlock_for_read<Clock>& for_read() {
90 return *this;
91 }
92
96 rwlock_for_write<Clock>& for_write() {
97 return *this;
98 }
99
103 future<> read_lock(typename semaphore_type::time_point timeout = semaphore_type::time_point::max()) {
104 return _sem.wait(timeout);
105 }
106
108 return _sem.wait(as);
109 }
110
114 void read_unlock() {
115 assert(_sem.current() < max_ops);
116 _sem.signal();
117 }
118
123 future<> write_lock(typename semaphore_type::time_point timeout = semaphore_type::time_point::max()) {
124 return _sem.wait(timeout, max_ops);
125 }
126
128 return _sem.wait(as, max_ops);
129 }
130
135 assert(_sem.current() == 0);
136 _sem.signal(max_ops);
137 }
138
141 return _sem.try_wait();
142 }
143
146 return _sem.try_wait(max_ops);
147 }
148
150
162 future<holder> hold_read_lock(typename semaphore_type::time_point timeout = semaphore_type::time_point::max()) {
163 return get_units(_sem, 1, timeout);
164 }
165
167 return get_units(_sem, 1, as);
168 }
169
181 future<holder> hold_write_lock(typename semaphore_type::time_point timeout = semaphore_type::time_point::max()) {
182 return get_units(_sem, max_ops, timeout);
183 }
184
186 return get_units(_sem, max_ops, as);
187 }
188
190 bool locked() const {
191 return _sem.available_units() != max_ops;
192 }
193
194 friend class rwlock_for_read<Clock>;
195 friend class rwlock_for_write<Clock>;
196};
197
198SEASTAR_MODULE_EXPORT
199using rwlock = basic_rwlock<>;
200
202
203}
Definition: abort_source.hh:58
Definition: rwlock.hh:75
future read_lock(typename semaphore_type::time_point timeout=semaphore_type::time_point::max())
Definition: rwlock.hh:103
void read_unlock()
Definition: rwlock.hh:114
future write_lock(typename semaphore_type::time_point timeout=semaphore_type::time_point::max())
Definition: rwlock.hh:123
bool try_read_lock()
Tries to acquire the lock in read mode iff this can be done without waiting.
Definition: rwlock.hh:140
bool try_write_lock()
Tries to acquire the lock in write mode iff this can be done without waiting.
Definition: rwlock.hh:145
rwlock_for_write< Clock > & for_write()
Definition: rwlock.hh:96
rwlock_for_read< Clock > & for_read()
Definition: rwlock.hh:89
future< holder > hold_read_lock(typename semaphore_type::time_point timeout=semaphore_type::time_point::max())
Definition: rwlock.hh:162
bool locked() const
Checks if any read or write locks are currently held.
Definition: rwlock.hh:190
future< holder > hold_write_lock(typename semaphore_type::time_point timeout=semaphore_type::time_point::max())
Definition: rwlock.hh:181
void write_unlock()
Definition: rwlock.hh:134
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:231
size_t current() const noexcept
Definition: semaphore.hh:446
future wait(size_t nr=1) noexcept
Definition: semaphore.hh:299
ssize_t available_units() const noexcept
Definition: semaphore.hh:452
bool try_wait(size_t nr=1) noexcept
Definition: semaphore.hh:434
void signal(size_t nr=1) noexcept
Definition: semaphore.hh:396
A representation of a possibly not-yet-computed value.
Definition: future.hh:1240
Definition: semaphore.hh:511
Seastar API namespace.
Definition: abort_on_ebadf.hh:26