@@ -47,11 +47,30 @@ class alignas(DEFAULT_CACHE_LINE_SIZE) SpinLock {
4747 void unlock () { __sync_fetch_and_sub (&_lock, 1 ); }
4848
4949 bool tryLockShared () {
50+ // Spins while no exclusive lock is held and the CAS to acquire a shared
51+ // lock fails (due to concurrent reader contention). Returns false ONLY when
52+ // an exclusive lock is observed (_lock > 0); never returns false spuriously.
5053 int value;
5154 while ((value = __atomic_load_n (&_lock, __ATOMIC_ACQUIRE)) <= 0 ) {
5255 if (__sync_bool_compare_and_swap (&_lock, value, value - 1 )) {
5356 return true ;
5457 }
58+ spinPause ();
59+ }
60+ return false ;
61+ }
62+
63+ // Signal-safe variant: returns false after at most 5 CAS attempts.
64+ // Use only in signal-handler paths where spinning indefinitely is unsafe.
65+ bool tryLockSharedBounded () {
66+ for (int attempts = 0 ; attempts < 5 ; ++attempts) {
67+ int value = __atomic_load_n (&_lock, __ATOMIC_ACQUIRE);
68+ if (value > 0 ) {
69+ return false ;
70+ }
71+ if (__sync_bool_compare_and_swap (&_lock, value, value - 1 )) {
72+ return true ;
73+ }
5574 }
5675 return false ;
5776 }
@@ -88,9 +107,9 @@ class SharedLockGuard {
88107class OptionalSharedLockGuard {
89108 SpinLock* _lock;
90109public:
91- OptionalSharedLockGuard (SpinLock* lock) : _lock(lock) {
110+ explicit OptionalSharedLockGuard (SpinLock* lock) : _lock(lock) {
92111 if (!_lock->tryLockShared ()) {
93- // Locking failed, no need to unlock.
112+ // Exclusive lock is held; no unlock needed. Only fails when an exclusive lock is observed .
94113 _lock = nullptr ;
95114 }
96115 }
@@ -108,6 +127,33 @@ class OptionalSharedLockGuard {
108127 OptionalSharedLockGuard& operator =(OptionalSharedLockGuard&&) = delete ;
109128};
110129
130+ // Signal-safe variant of OptionalSharedLockGuard: uses bounded CAS retries
131+ // and may fail spuriously when racing other shared lockers. Use ONLY in
132+ // signal-handler paths where spinning indefinitely is unsafe; do NOT use
133+ // in hot recording paths where silent acquisition failures would drop events.
134+ class BoundedOptionalSharedLockGuard {
135+ SpinLock* _lock;
136+ public:
137+ explicit BoundedOptionalSharedLockGuard (SpinLock* lock) : _lock(lock) {
138+ if (!_lock->tryLockSharedBounded ()) {
139+ // Locking failed (bounded retries exhausted or exclusive lock held); no unlock needed.
140+ _lock = nullptr ;
141+ }
142+ }
143+ ~BoundedOptionalSharedLockGuard () {
144+ if (_lock != nullptr ) {
145+ _lock->unlockShared ();
146+ }
147+ }
148+ bool ownsLock () { return _lock != nullptr ; }
149+
150+ // Non-copyable and non-movable
151+ BoundedOptionalSharedLockGuard (const BoundedOptionalSharedLockGuard&) = delete ;
152+ BoundedOptionalSharedLockGuard& operator =(const BoundedOptionalSharedLockGuard&) = delete ;
153+ BoundedOptionalSharedLockGuard (BoundedOptionalSharedLockGuard&&) = delete ;
154+ BoundedOptionalSharedLockGuard& operator =(BoundedOptionalSharedLockGuard&&) = delete ;
155+ };
156+
111157class ExclusiveLockGuard {
112158private:
113159 SpinLock* _lock;
0 commit comments