@@ -13,34 +13,34 @@ namespace nbl::system
13
13
// Ugly workaround, structs with constevals can't be nested
14
14
namespace impl
15
15
{
16
- template <typename U>
17
- struct DPWRLStateLock
18
- {
19
- using type = std::atomic<U>;
20
- };
21
16
22
- // will fail if `atomic_unsiged_lock_free` doesn't exist or its value type has wrong size
23
- template <typename U> requires (sizeof (std::atomic_unsigned_lock_free::value_type) >= sizeof(U))
24
- struct DPWRLStateLock<U>
25
- {
26
- using type = std::atomic_unsigned_lock_free;
27
- };
17
+ template <typename U>
18
+ struct DPWRLStateLock
19
+ {
20
+ using type = std::atomic<U>;
21
+ };
28
22
29
- struct DPWRLStateSemantics
30
- {
31
- using state_lock_value_t = typename DPWRLStateLock<uint32_t >::type::value_type;
32
- uint32_t currentReaders : 10 = 0 ;
33
- uint32_t pendingWriters : 10 = 0 ;
34
- uint32_t pendingUpgrades : 10 = 0 ;
35
- uint32_t writing : 1 = 0 ;
36
- uint32_t stateLocked : 1 = 0 ;
37
-
38
- consteval inline operator state_lock_value_t () const
39
- {
40
- return static_cast <state_lock_value_t >((currentReaders << 22 ) | (pendingWriters << 12 ) | (pendingUpgrades << 2 ) | (writing << 1 ) | stateLocked);
41
- }
42
- };
43
- } // namespace impl
23
+ // will fail if `atomic_unsiged_lock_free` doesn't exist or its value type has wrong size
24
+ template <typename U> requires (sizeof (std::atomic_unsigned_lock_free::value_type) >= sizeof(U))
25
+ struct DPWRLStateLock<U>
26
+ {
27
+ using type = std::atomic_unsigned_lock_free;
28
+ };
29
+
30
+ struct DPWRLStateSemantics
31
+ {
32
+ using state_lock_value_t = typename DPWRLStateLock<uint32_t >::type::value_type;
33
+ uint32_t currentReaders : 10 = 0 ;
34
+ uint32_t pendingWriters : 10 = 0 ;
35
+ uint32_t pendingUpgrades : 10 = 0 ;
36
+ uint32_t writing : 1 = 0 ;
37
+ uint32_t stateLocked : 1 = 0 ;
38
+
39
+ consteval inline operator state_lock_value_t () const
40
+ {
41
+ return static_cast <state_lock_value_t >((currentReaders << 22 ) | (pendingWriters << 12 ) | (pendingUpgrades << 2 ) | (writing << 1 ) | stateLocked);
42
+ }
43
+ };
44
44
45
45
enum DPWR_LOCK_DEBUG_STAGE
46
46
{
@@ -51,19 +51,21 @@ enum DPWR_LOCK_DEBUG_STAGE
51
51
PREEMPTED
52
52
};
53
53
54
- namespace impl
54
+ struct DPWRLVoidDebugCallback
55
55
{
56
- template <typename T>
57
- concept DPWRLDebugCallback = requires (T t, DPWR_LOCK_DEBUG_STAGE stage) {
58
- { t (stage) } -> std::same_as<void >;
59
- };
56
+ };
57
+
58
+ template <typename T>
59
+ /* *
60
+ * @brief A valid debug callback overrides `void operator()(DPWR_LOCK_DEBUG_STAGE stage)`
61
+ */
62
+ concept DPWRLDebugCallback = requires (T t, DPWR_LOCK_DEBUG_STAGE stage) {
63
+ { t (stage) } -> std::same_as<void >;
64
+ } || std::is_same_v<T, DPWRLVoidDebugCallback>;
65
+
66
+ } // namespace impl
67
+
60
68
61
- class DPWRLVoidDebugCallback
62
- {
63
- public:
64
- void operator ()(DPWR_LOCK_DEBUG_STAGE) {};
65
- };
66
- }
67
69
68
70
template <impl::DPWRLDebugCallback DebugCallback = impl::DPWRLVoidDebugCallback>
69
71
/* *
@@ -265,7 +267,7 @@ class demote_promote_writer_readers_lock_debug
265
267
266
268
private:
267
269
268
- constexpr static inline bool usingDebugCallback = std::is_same_v<DebugCallback, impl::DPWRLVoidDebugCallback>;
270
+ constexpr static inline bool usingDebugCallback = ! std::is_same_v<DebugCallback, impl::DPWRLVoidDebugCallback>;
269
271
270
272
struct DefaultPreemptionCheck
271
273
{
@@ -286,6 +288,7 @@ class demote_promote_writer_readers_lock_debug
286
288
Preempted& preempted = defaultPreempted
287
289
)
288
290
{
291
+ DebugCallback callback = {};
289
292
for (uint32_t spinCount = 0 ; true ; spinCount++)
290
293
{
291
294
const state_lock_value_t oldState = state.fetch_or (flipLock);
@@ -301,14 +304,14 @@ class demote_promote_writer_readers_lock_debug
301
304
const state_lock_value_t newState = wasPreempted ? preempted (oldState) : success (oldState);
302
305
// new state must unlock the state lock
303
306
assert (!(newState & flipLock));
304
- if (usingDebugCallback) DebugCallback ( DPWR_LOCK_DEBUG_STAGE::BEFORE_STATE_UPDATE);
307
+ if constexpr (usingDebugCallback) callback (impl:: DPWR_LOCK_DEBUG_STAGE::BEFORE_STATE_UPDATE);
305
308
state.store (newState);
306
- if (usingDebugCallback) DebugCallback ( DPWR_LOCK_DEBUG_STAGE::AFTER_STATE_UPDATE);
309
+ if constexpr (usingDebugCallback) callback (impl:: DPWR_LOCK_DEBUG_STAGE::AFTER_STATE_UPDATE);
307
310
if (wasPreempted)
308
311
{
309
- if (usingDebugCallback)
312
+ if constexpr (usingDebugCallback)
310
313
{
311
- DebugCallback ( DPWR_LOCK_DEBUG_STAGE::PREEMPTED);
314
+ callback (impl:: DPWR_LOCK_DEBUG_STAGE::PREEMPTED);
312
315
}
313
316
else
314
317
{
@@ -333,34 +336,48 @@ class demote_promote_writer_readers_lock_debug
333
336
334
337
namespace impl
335
338
{
336
- template <impl::DPWRLDebugCallback DebugCallback = impl::DPWRLVoidDebugCallback>
337
- class dpwr_lock_guard_base
339
+
340
+ template <impl::DPWRLDebugCallback DebugCallback = impl::DPWRLVoidDebugCallback>
341
+ class dpwr_lock_guard_base
342
+ {
343
+ dpwr_lock_guard_base () : m_lock(nullptr ) {}
344
+
345
+ public:
346
+ using dpwr_lock_t = demote_promote_writer_readers_lock_debug<DebugCallback>;
347
+ dpwr_lock_guard_base& operator =(const dpwr_lock_guard_base&) = delete ;
348
+ dpwr_lock_guard_base (const dpwr_lock_guard_base&) = delete ;
349
+
350
+ dpwr_lock_guard_base& operator =(dpwr_lock_guard_base&& rhs) noexcept
338
351
{
339
- dpwr_lock_guard_base () : m_lock(nullptr ) {}
352
+ m_lock = rhs.m_lock ;
353
+ rhs.m_lock = nullptr ;
354
+ return *this ;
355
+ }
356
+ dpwr_lock_guard_base (dpwr_lock_guard_base&& rhs) noexcept : dpwr_lock_guard_base()
357
+ {
358
+ operator =(std::move (rhs));
359
+ }
340
360
341
- public:
342
- using dpwr_lock_t = typename demote_promote_writer_readers_lock_debug<DebugCallback>;
343
- dpwr_lock_guard_base& operator =(const dpwr_lock_guard_base&) = delete ;
344
- dpwr_lock_guard_base (const dpwr_lock_guard_base&) = delete ;
361
+ /* *
362
+ * @brief Checks whether this guard is currently locking the lock `lk`
363
+ */
364
+ bool hasLocked (dpwr_lock_t & lk) const
365
+ {
366
+ return m_lock == &lk;
367
+ }
345
368
346
- dpwr_lock_guard_base& operator =(dpwr_lock_guard_base&& rhs) noexcept
347
- {
348
- m_lock = rhs.m_lock ;
349
- rhs.m_lock = nullptr ;
350
- return *this ;
351
- }
352
- dpwr_lock_guard_base (dpwr_lock_guard_base&& rhs) noexcept : dpwr_lock_guard_base()
353
- {
354
- operator =(std::move (rhs));
355
- }
369
+ protected:
370
+ dpwr_lock_guard_base (dpwr_lock_t & lk) noexcept : m_lock(&lk) {}
356
371
357
- protected:
358
- dpwr_lock_guard_base ( dpwr_lock_t & lk) noexcept : m_lock(&lk) {}
372
+ dpwr_lock_t * m_lock;
373
+ };
359
374
360
- dpwr_lock_t * m_lock;
361
- };
362
375
} // namespace impl
363
376
377
+ // Forward declaration required by GCC
378
+ template <impl::DPWRLDebugCallback DebugCallback>
379
+ class dpwr_write_lock_guard_debug ;
380
+
364
381
template <impl::DPWRLDebugCallback DebugCallback = impl::DPWRLVoidDebugCallback>
365
382
class dpwr_read_lock_guard_debug : public impl ::dpwr_lock_guard_base<DebugCallback>
366
383
{
@@ -404,13 +421,13 @@ class dpwr_write_lock_guard_debug : public impl::dpwr_lock_guard_base<DebugCallb
404
421
};
405
422
406
423
template <impl::DPWRLDebugCallback DebugCallback>
407
- inline dpwr_read_lock_guard_debug<DebugCallback>::dpwr_read_lock_guard_debug(dpwr_write_lock_guard_debug<DebugCallback>&& wl) : impl::dpwr_lock_guard_base(std::move(wl))
424
+ inline dpwr_read_lock_guard_debug<DebugCallback>::dpwr_read_lock_guard_debug(dpwr_write_lock_guard_debug<DebugCallback>&& wl) : impl::dpwr_lock_guard_base<DebugCallback> (std::move(wl))
408
425
{
409
426
this ->m_lock ->downgrade ();
410
427
}
411
428
412
429
template <impl::DPWRLDebugCallback DebugCallback>
413
- inline dpwr_write_lock_guard_debug<DebugCallback>::dpwr_write_lock_guard_debug(dpwr_read_lock_guard_debug<DebugCallback>&& rl) : impl::dpwr_lock_guard_base(std::move(rl))
430
+ inline dpwr_write_lock_guard_debug<DebugCallback>::dpwr_write_lock_guard_debug(dpwr_read_lock_guard_debug<DebugCallback>&& rl) : impl::dpwr_lock_guard_base<DebugCallback> (std::move(rl))
414
431
{
415
432
this ->m_lock ->upgrade ();
416
433
}
0 commit comments