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 
30 namespace seastar {
31 
33 // lock / unlock semantics for rwlock, so it can be used with with_lock()
34 SEASTAR_MODULE_EXPORT
35 template<typename Clock>
36 class basic_rwlock;
37 
38 template<typename Clock = typename timer<>::clock>
39 class rwlock_for_read {
40 public:
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 
50 template<typename Clock = typename timer<>::clock>
51 class rwlock_for_write {
52 public:
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 
73 SEASTAR_MODULE_EXPORT
74 template<typename Clock = typename timer<>::clock>
75 class 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;
81 public:
82  basic_rwlock()
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 
134  void write_unlock() {
135  assert(_sem.current() == 0);
136  _sem.signal(max_ops);
137  }
138 
140  bool try_read_lock() {
141  return _sem.try_wait();
142  }
143 
145  bool try_write_lock() {
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 
198 SEASTAR_MODULE_EXPORT
199 using rwlock = basic_rwlock<>;
200 
202 
203 }
Definition: abort_source.hh:59
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
rwlock_for_read< Clock > & for_read()
Definition: rwlock.hh:89
future< holder > hold_write_lock(typename semaphore_type::time_point timeout=semaphore_type::time_point::max())
Definition: rwlock.hh:181
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
bool locked() const
Checks if any read or write locks are currently held.
Definition: rwlock.hh:190
future< holder > hold_read_lock(typename semaphore_type::time_point timeout=semaphore_type::time_point::max())
Definition: rwlock.hh:162
rwlock_for_write< Clock > & for_write()
Definition: rwlock.hh:96
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
Definition: semaphore.hh:511
Seastar API namespace.
Definition: abort_on_ebadf.hh:26