libosmscout 1.1.1
Loading...
Searching...
No Matches
ReadWriteLock.h
Go to the documentation of this file.
1#ifndef LIBOSMSCOUT_READWRITELOCK_H
2#define LIBOSMSCOUT_READWRITELOCK_H
3
4/*
5 This source is part of the libosmscout library
6 Copyright (C) 2024 Jean-Luc Barriere
7
8 This library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Lesser General Public
10 License as published by the Free Software Foundation; either
11 version 2.1 of the License, or (at your option) any later version.
12
13 This library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public
19 License along with this library; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
22
24
25#include <atomic>
26#include <thread>
27#include <mutex>
28#include <condition_variable>
29
30namespace osmscout {
31
38
40private:
41 mutable std::atomic<bool> s_spin = false;
42
43 volatile int x_wait = 0; /* counts requests in wait for X */
44 volatile int x_flag = 0; /* X status: 0, 1, 2, or 3 */
45 std::thread::id x_owner; /* X owner (thread id) */
46
47 std::mutex x_gate_lock;
48 std::condition_variable x_gate; /* wait for release of X */
49 std::mutex s_gate_lock;
50 std::condition_variable s_gate; /* wait for release of S */
51
52 bool px = true; /* enable X precedence */
53
54 struct TNode {
55 TNode * _prev = nullptr;
56 TNode * _next = nullptr;
57 std::thread::id id;
58 int count = 0;
59 };
60 TNode * s_freed = nullptr;
61 TNode * s_nodes = nullptr;
62
63 void spin_lock() {
64 while (s_spin.exchange(true, std::memory_order_acquire)) {
65 do {
66 std::this_thread::yield();
67 } while (s_spin.load(std::memory_order_relaxed));
68 }
69 }
70 void spin_unlock() {
71 s_spin.store(false, std::memory_order_release);
72 }
73
74 TNode * find_node(const std::thread::id& id);
75 TNode * new_node(const std::thread::id& id);
76 void free_node(TNode * n);
77
78public:
80 explicit Latch(bool _px) : px(_px) { }
81 Latch(const Latch&) = delete;
82 Latch(Latch&&) = delete;
83 Latch& operator=(const Latch&) = delete;
84 Latch& operator=(Latch&&) = delete;
86
87 /* Locks the latch for exclusive ownership,
88 * blocks if the latch is not available
89 */
90 void lock();
91
92 /* Unlocks the latch (exclusive ownership) */
93 void unlock();
94
95 /* Locks the latch for shared ownership,
96 * blocks if the latch is not available
97 */
99
100 /* Unlocks the latch (shared ownership) */
102
103 /* Tries to lock the latch for shared ownership,
104 * returns true if the latch has no exclusive ownership or any request for
105 * exclusive ownership, else false
106 */
108};
109
110/*
111 * Cannot use the template std::shared_lock as Latch does not implement all the
112 * requirements of the standard
113 */
115{
116private:
117 Latch *p = nullptr;
118 bool owns = false;
119
120 void swap(ReadLock& rl) noexcept {
121 std::swap(p, rl.p);
122 std::swap(owns, rl.owns);
123 }
124
125public:
126
127 ReadLock() = default;
128
129 explicit ReadLock(Latch& latch) : p(&latch), owns(true) { latch.lock_shared(); }
130
131 /* Assume the calling thread already has ownership of the shared lock */
132 ReadLock(Latch& latch, std::adopt_lock_t) : p(&latch), owns(true) { }
133
135 if (owns) {
136 p->unlock_shared();
137 }
138 }
139
140 ReadLock(ReadLock const&) = delete;
141 ReadLock& operator=(ReadLock const&) = delete;
142
143 ReadLock(ReadLock&& rl) noexcept { swap(rl); }
144
145 ReadLock& operator=(ReadLock&& rl) noexcept {
146 swap(rl);
147 return *this;
148 }
149
150 bool owns_lock() const noexcept {
151 return owns;
152 }
153
154 void lock() {
155 if (!owns && p != nullptr) {
156 p->lock_shared();
157 owns = true;
158 }
159 }
160
161 void unlock() {
162 if (owns) {
163 owns = false;
164 p->unlock_shared();
165 }
166 }
167
168 bool try_lock() {
169 if (!owns && p != nullptr) {
170 owns = p->try_lock_shared();
171 }
172 return owns;
173 }
174};
175
176/*
177 * Cannot use the template std::unique_lock as Latch does not implement all the
178 * requirements of the standard
179 */
181{
182private:
183 Latch *p = nullptr;
184 bool owns = false;
185
186 void swap(WriteLock& wl) noexcept {
187 std::swap(p, wl.p);
188 std::swap(owns, wl.owns);
189 }
190
191public:
192
193 WriteLock() = default;
194
195 explicit WriteLock(Latch& latch) : p(&latch), owns(true) { latch.lock(); }
196
198 if (owns) {
199 p->unlock();
200 }
201 }
202
203 WriteLock(WriteLock const&) = delete;
204 WriteLock& operator=(WriteLock const&) = delete;
205
206 WriteLock(WriteLock&& wl) noexcept { swap(wl); }
207
208 WriteLock& operator=(WriteLock&& wl) noexcept {
209 swap(wl);
210 return *this;
211 }
212
213 bool owns_lock() const noexcept {
214 return owns;
215 }
216
217 void lock() {
218 if (!owns && p != nullptr) {
219 p->lock();
220 owns = true;
221 }
222 }
223
224 void unlock() {
225 if (owns) {
226 owns = false;
227 p->unlock();
228 }
229 }
230};
231
232}
233
234#endif //LIBOSMSCOUT_READWRITELOCK_H
#define OSMSCOUT_API
Definition CoreImportExport.h:45
Definition ReadWriteLock.h:39
Latch(Latch &&)=delete
Latch(const Latch &)=delete
bool try_lock_shared()
Latch & operator=(const Latch &)=delete
Latch & operator=(Latch &&)=delete
Latch(bool _px)
Definition ReadWriteLock.h:80
void unlock_shared()
bool try_lock()
Definition ReadWriteLock.h:168
ReadLock & operator=(ReadLock &&rl) noexcept
Definition ReadWriteLock.h:145
ReadLock(ReadLock const &)=delete
~ReadLock()
Definition ReadWriteLock.h:134
ReadLock(Latch &latch)
Definition ReadWriteLock.h:129
bool owns_lock() const noexcept
Definition ReadWriteLock.h:150
ReadLock(Latch &latch, std::adopt_lock_t)
Definition ReadWriteLock.h:132
ReadLock & operator=(ReadLock const &)=delete
ReadLock(ReadLock &&rl) noexcept
Definition ReadWriteLock.h:143
void unlock()
Definition ReadWriteLock.h:161
void lock()
Definition ReadWriteLock.h:154
~WriteLock()
Definition ReadWriteLock.h:197
WriteLock & operator=(WriteLock &&wl) noexcept
Definition ReadWriteLock.h:208
WriteLock(WriteLock const &)=delete
WriteLock & operator=(WriteLock const &)=delete
void lock()
Definition ReadWriteLock.h:217
bool owns_lock() const noexcept
Definition ReadWriteLock.h:213
WriteLock(Latch &latch)
Definition ReadWriteLock.h:195
void unlock()
Definition ReadWriteLock.h:224
WriteLock(WriteLock &&wl) noexcept
Definition ReadWriteLock.h:206
Definition Area.h:39