Lumiera 0.pre.04
»edit your freedom«
Loading...
Searching...
No Matches
sync.hpp
Go to the documentation of this file.
1/*
2 SYNC.hpp - generic helper for object based locking and synchronisation
3
4 Copyright (C)
5 2007, Christian Thaeter <ct@pipapo.org>
6 2008, Hermann Vosseler <Ichthyostega@web.de>
7 2023, Hermann Vosseler <Ichthyostega@web.de>
8
9  **Lumiera** is free software; you can redistribute it and/or modify it
10  under the terms of the GNU General Public License as published by the
11  Free Software Foundation; either version 2 of the License, or (at your
12  option) any later version. See the file COPYING for further details.
13
14*/
15
63#ifndef LIB_SYNC_H
64#define LIB_SYNC_H
65
66#include "lib/error.hpp"
67#include "lib/nocopy.hpp"
68#include "lib/util.hpp"
69
70#include <mutex>
71#include <condition_variable>
72#include <chrono>
73
74
75namespace lib {
76
78 namespace sync {
79
80 /* ========== policies to define required degree of locking functionality ============== */
81
82 template<class MTX>
83 struct Condition
84 : MTX
85 , std::condition_variable_any
86 {
87
88 template<class PRED>
89 void
90 wait (PRED&& predicate)
91 {
92 condVar().wait (mutex(), std::forward<PRED> (predicate));
93 }
94
98 template<class REPR, class PERI, class PRED>
99 bool
100 wait_for (std::chrono::duration<REPR, PERI> const& timeout, PRED&& predicate)
101 {
102 return condVar().wait_for (mutex(), timeout, std::forward<PRED> (predicate));
103 }
104
105 MTX&
107 {
108 return static_cast<MTX&> (*this);
109 }
110 std::condition_variable_any&
112 {
113 return static_cast<std::condition_variable_any&> (*this);
114 }
115 };
116
118 {
119 void lock() { /* boo */ }
120 void unlock() noexcept { /* hoo */ }
121 };
122
123
124
125 /* ========== Object Monitor ============== */
126
132 template<class IMPL>
134 : IMPL
136 {
137 public:
138
139 void lock() { IMPL::lock(); }
140 void unlock() noexcept { IMPL::unlock(); }
141
142 void notify_one() noexcept { IMPL::notify_one(); }
143 void notify_all() noexcept { IMPL::notify_all(); }
144
145 template<class PRED>
146 void
147 wait (PRED&& predicate)
148 {
149 IMPL::wait (std::forward<PRED>(predicate));
150 }
151
152 template<class DUR, class PRED>
153 bool
154 wait_for (DUR const& timeout, PRED&& predicate)
155 {
156 return IMPL::wait_for (timeout, std::forward<PRED> (predicate));
157 }
158 };
159
160 using NonrecursiveLock_NoWait = std::mutex;
161 using RecursiveLock_NoWait = std::recursive_mutex;
164
165
166 } // namespace sync (helpers and building blocks)
167
168
169
170
171
172 /* Interface to be used by client code:
173 * Inherit from class Sync with a suitable Policy.
174 * Then use the embedded Lock class.
175 */
176
177 /* ======= Policy classes ======= */
178
183
184
185 /*********************************************************************/
208 template<class CONF = NonrecursiveLock_NoWait>
209 class Sync
210 {
213
214 public:
215 static Monitor&
216 getMonitor(Sync const* forThis)
217 {
218 REQUIRE (forThis);
219 return forThis->objectMonitor_;
220 }
221
222
223 /*****************************************/
226 class Lock
228 {
230
231 public:
232 template<class X>
233 Lock(X* it) : mon_{getMonitor(it)}{ mon_.lock(); }
235
238
239 template<class PRED>
240 void
241 wait (PRED&& predicate)
242 {
243 mon_.wait (std::forward<PRED>(predicate));
244 }
245
246 template<class DUR, class PRED>
247 bool
248 wait_for (DUR const& timeout, PRED&& predicate)
249 {
250 return mon_.wait_for (timeout, std::forward<PRED> (predicate));
251 }
252
256 template<class X, class PRED>
257 Lock(X* it, PRED&& predicate)
258 : mon_(getMonitor(it))
259 {
260 mon_.lock();
261 try {
262 mon_.wait (std::forward<PRED>(predicate));
263 }
264 catch(...)
265 {
266 mon_.unlock();
267 throw;
268 }
269 }
270
271 protected:
274 : mon_{m}
275 {
276 mon_.lock();
277 }
278
281 };
282 };
283
284
285} // namespace lumiera
286#endif
scoped guard to control the actual locking.
Definition sync.hpp:228
Lock(Monitor &m)
for creating a ClassLock
Definition sync.hpp:273
Lock(X *it)
Definition sync.hpp:233
void wait(PRED &&predicate)
Definition sync.hpp:241
Monitor & accessMonitor()
subclass access to underlying sync primitives
Definition sync.hpp:280
void notify_one()
Definition sync.hpp:236
bool wait_for(DUR const &timeout, PRED &&predicate)
Definition sync.hpp:248
Lock(X *it, PRED &&predicate)
convenience shortcut: Locks and immediately enters wait state on the given predicate
Definition sync.hpp:257
Monitor & mon_
Definition sync.hpp:229
void notify_all()
Definition sync.hpp:237
Facility for monitor object based locking.
Definition sync.hpp:210
static Monitor & getMonitor(Sync const *forThis)
Definition sync.hpp:216
Monitor objectMonitor_
Definition sync.hpp:212
Object Monitor for synchronisation and waiting.
Definition sync.hpp:136
void notify_all() noexcept
Definition sync.hpp:143
void wait(PRED &&predicate)
Definition sync.hpp:147
void unlock() noexcept
Definition sync.hpp:140
bool wait_for(DUR const &timeout, PRED &&predicate)
Definition sync.hpp:154
void notify_one() noexcept
Definition sync.hpp:142
Any copy and copy construction prohibited.
Definition nocopy.hpp:38
Lumiera error handling (C++ interface).
std::recursive_mutex RecursiveLock_NoWait
Definition sync.hpp:161
std::mutex NonrecursiveLock_NoWait
Definition sync.hpp:160
Implementation namespace for support and library code.
Mix-Ins to allow or prohibit various degrees of copying and cloning.
void wait(PRED &&predicate)
Definition sync.hpp:90
bool wait_for(std::chrono::duration< REPR, PERI > const &timeout, PRED &&predicate)
Definition sync.hpp:100
std::condition_variable_any & condVar()
Definition sync.hpp:111
void unlock() noexcept
Definition sync.hpp:120
Tiny helper functions and shortcuts to be used everywhere Consider this header to be effectively incl...