summaryrefslogtreecommitdiffstats
path: root/library/cpp/threading/light_rw_lock
diff options
context:
space:
mode:
authoragri <[email protected]>2022-02-10 16:48:12 +0300
committerDaniil Cherednik <[email protected]>2022-02-10 16:48:12 +0300
commitd3530b2692e400bd4d29bd4f07cafaee139164e7 (patch)
treeb7ae636a74490e649a2ed0fdd5361f1bec83b9f9 /library/cpp/threading/light_rw_lock
parent0f4c5d1e8c0672bf0a1f2f2d8acac5ba24772435 (diff)
Restoring authorship annotation for <[email protected]>. Commit 1 of 2.
Diffstat (limited to 'library/cpp/threading/light_rw_lock')
-rw-r--r--library/cpp/threading/light_rw_lock/bench/lightrwlock_test.cpp370
-rw-r--r--library/cpp/threading/light_rw_lock/bench/ya.make24
-rw-r--r--library/cpp/threading/light_rw_lock/lightrwlock.cpp224
-rw-r--r--library/cpp/threading/light_rw_lock/lightrwlock.h254
-rw-r--r--library/cpp/threading/light_rw_lock/ut/rwlock_ut.cpp236
-rw-r--r--library/cpp/threading/light_rw_lock/ut/ya.make14
-rw-r--r--library/cpp/threading/light_rw_lock/ya.make20
7 files changed, 571 insertions, 571 deletions
diff --git a/library/cpp/threading/light_rw_lock/bench/lightrwlock_test.cpp b/library/cpp/threading/light_rw_lock/bench/lightrwlock_test.cpp
index c3027ea5449..5e217c25ade 100644
--- a/library/cpp/threading/light_rw_lock/bench/lightrwlock_test.cpp
+++ b/library/cpp/threading/light_rw_lock/bench/lightrwlock_test.cpp
@@ -1,188 +1,188 @@
#include <library/cpp/threading/light_rw_lock/lightrwlock.h>
-#include <util/random/random.h>
-
-#ifdef _linux_
-// Light rw lock is implemented only for linux
-
-using namespace NS_LightRWLock;
-
-#include <pthread.h>
-#include <stdlib.h>
-#include <stdio.h>
-
-#define LIGHT
-
-#ifdef RWSPINLOCK
+#include <util/random/random.h>
+
+#ifdef _linux_
+// Light rw lock is implemented only for linux
+
+using namespace NS_LightRWLock;
+
+#include <pthread.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#define LIGHT
+
+#ifdef RWSPINLOCK
#include <library/cpp/lwtrace/rwspinlock.h>
-#endif
-
-#define CHECK_LOGIC 1
-#define LOOPCOUNT 1000000
-#define RANRCOUNT 100
-#define THREADCOUNT 40
-#define WRITELOCKS 100
-
-#if defined(_MSC_VER)
-static int Y_FORCE_INLINE AtomicFetchAdd(volatile int& item, int value) {
- return _InterlockedExchangeAdd((&item, value);
-}
-#elif defined(__GNUC__)
-#else
+#endif
+
+#define CHECK_LOGIC 1
+#define LOOPCOUNT 1000000
+#define RANRCOUNT 100
+#define THREADCOUNT 40
+#define WRITELOCKS 100
+
+#if defined(_MSC_VER)
+static int Y_FORCE_INLINE AtomicFetchAdd(volatile int& item, int value) {
+ return _InterlockedExchangeAdd((&item, value);
+}
+#elif defined(__GNUC__)
+#else
#error unsupported platform
-#endif
-
-class TPosixRWLock {
-public:
- TPosixRWLock() {
- }
-
- ~TPosixRWLock() {
- pthread_rwlock_destroy(&rwlock);
- }
-
- TPosixRWLock(const TPosixRWLock&) = delete;
- void operator=(const TPosixRWLock&) = delete;
-
-private:
- pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER;
- friend class TPosixRWShareLocker;
- friend class TPosixRWExclusiveLocker;
-};
-
-#if defined(LIGHT)
-TLightRWLock __attribute__((aligned(64))) rwlock;
-#elif defined(POSIX)
-TPosixRWLock rwlock;
-#elif defined(RWSPINLOCK)
-TRWSpinLock __attribute__((aligned(64))) rwlock;
-#else
-#error "define lock type"
-#endif
-
-volatile __attribute__((aligned(64))) int checkIt = 0;
-volatile int checkExcl = 0;
-
-class TPosixRWShareLocker {
-public:
- TPosixRWShareLocker(TPosixRWLock& lock)
- : LockP_(&lock)
- {
- pthread_rwlock_rdlock(&LockP_->rwlock);
- }
-
- ~TPosixRWShareLocker() {
- pthread_rwlock_unlock(&LockP_->rwlock);
- }
-
- TPosixRWShareLocker(const TPosixRWShareLocker&) = delete;
- void operator=(const TPosixRWShareLocker&) = delete;
-
-private:
- TPosixRWLock* LockP_;
-};
-
-class TPosixRWExclusiveLocker {
-public:
- TPosixRWExclusiveLocker(TPosixRWLock& lock)
- : LockP_(&lock)
- {
- pthread_rwlock_wrlock(&LockP_->rwlock);
- }
-
- ~TPosixRWExclusiveLocker() {
- pthread_rwlock_unlock(&LockP_->rwlock);
- }
- TPosixRWExclusiveLocker(const TPosixRWExclusiveLocker&) = delete;
- void operator=(const TPosixRWExclusiveLocker&) = delete;
-
-private:
- TPosixRWLock* LockP_;
-};
-
-template <typename TLocker, bool excl>
-static Y_FORCE_INLINE void Run() {
- TLocker lockIt(rwlock);
-
-#if defined(CHECK_LOGIC) && CHECK_LOGIC
- if (!excl && checkExcl == 1) {
- printf("there is a bug\n");
- }
-
- int result = AtomicFetchAdd(checkIt, 1);
- if (excl)
- checkExcl = 1;
-
- if (excl && result > 1)
- printf("there is a bug\n");
-#endif
-
- for (unsigned w = 0; w < RANRCOUNT; ++w)
- RandomNumber<ui32>();
-
-#if defined(CHECK_LOGIC) && CHECK_LOGIC
- if (excl)
- checkExcl = 0;
-
- AtomicFetchAdd(checkIt, -1);
-#endif
-}
-
-#ifdef LIGHT
-static void* fast_thread_start(__attribute__((unused)) void* arg) {
- for (unsigned q = 0; q < LOOPCOUNT; ++q) {
- char excl = (RandomNumber<ui32>() % WRITELOCKS) == 0;
- if (excl)
- Run<TLightWriteGuard, 1>();
- else
- Run<TLightReadGuard, 0>();
- }
- return NULL;
-}
-#endif
-
-#ifdef POSIX
-static void* fast_thread_start(__attribute__((unused)) void* arg) {
- for (unsigned q = 0; q < LOOPCOUNT; ++q) {
- char excl = (RandomNumber<ui32>() % WRITELOCKS) == 0;
- if (excl)
- Run<TPosixRWExclusiveLocker, 1>();
- else
- Run<TPosixRWShareLocker, 0>();
- }
- return NULL;
-}
-#endif
-
-#ifdef RWSPINLOCK
-static void* fast_thread_start(__attribute__((unused)) void* arg) {
- for (unsigned q = 0; q < LOOPCOUNT; ++q) {
- char excl = (RandomNumber<ui32>() % WRITELOCKS) == 0;
- if (excl)
- Run<TWriteSpinLockGuard, 1>();
- else
- Run<TReadSpinLockGuard, 0>();
- }
- return NULL;
-}
-#endif
-
-int main() {
- pthread_t threads[THREADCOUNT];
-
- for (unsigned q = 0; q < THREADCOUNT; ++q) {
- pthread_create(&(threads[q]), NULL, &fast_thread_start, NULL);
- }
-
- for (unsigned q = 0; q < THREADCOUNT; ++q)
- pthread_join(threads[q], NULL);
-
- return 0;
-}
-
-#else // !_linux_
-
-int main() {
- return 0;
-}
-
-#endif
+#endif
+
+class TPosixRWLock {
+public:
+ TPosixRWLock() {
+ }
+
+ ~TPosixRWLock() {
+ pthread_rwlock_destroy(&rwlock);
+ }
+
+ TPosixRWLock(const TPosixRWLock&) = delete;
+ void operator=(const TPosixRWLock&) = delete;
+
+private:
+ pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER;
+ friend class TPosixRWShareLocker;
+ friend class TPosixRWExclusiveLocker;
+};
+
+#if defined(LIGHT)
+TLightRWLock __attribute__((aligned(64))) rwlock;
+#elif defined(POSIX)
+TPosixRWLock rwlock;
+#elif defined(RWSPINLOCK)
+TRWSpinLock __attribute__((aligned(64))) rwlock;
+#else
+#error "define lock type"
+#endif
+
+volatile __attribute__((aligned(64))) int checkIt = 0;
+volatile int checkExcl = 0;
+
+class TPosixRWShareLocker {
+public:
+ TPosixRWShareLocker(TPosixRWLock& lock)
+ : LockP_(&lock)
+ {
+ pthread_rwlock_rdlock(&LockP_->rwlock);
+ }
+
+ ~TPosixRWShareLocker() {
+ pthread_rwlock_unlock(&LockP_->rwlock);
+ }
+
+ TPosixRWShareLocker(const TPosixRWShareLocker&) = delete;
+ void operator=(const TPosixRWShareLocker&) = delete;
+
+private:
+ TPosixRWLock* LockP_;
+};
+
+class TPosixRWExclusiveLocker {
+public:
+ TPosixRWExclusiveLocker(TPosixRWLock& lock)
+ : LockP_(&lock)
+ {
+ pthread_rwlock_wrlock(&LockP_->rwlock);
+ }
+
+ ~TPosixRWExclusiveLocker() {
+ pthread_rwlock_unlock(&LockP_->rwlock);
+ }
+ TPosixRWExclusiveLocker(const TPosixRWExclusiveLocker&) = delete;
+ void operator=(const TPosixRWExclusiveLocker&) = delete;
+
+private:
+ TPosixRWLock* LockP_;
+};
+
+template <typename TLocker, bool excl>
+static Y_FORCE_INLINE void Run() {
+ TLocker lockIt(rwlock);
+
+#if defined(CHECK_LOGIC) && CHECK_LOGIC
+ if (!excl && checkExcl == 1) {
+ printf("there is a bug\n");
+ }
+
+ int result = AtomicFetchAdd(checkIt, 1);
+ if (excl)
+ checkExcl = 1;
+
+ if (excl && result > 1)
+ printf("there is a bug\n");
+#endif
+
+ for (unsigned w = 0; w < RANRCOUNT; ++w)
+ RandomNumber<ui32>();
+
+#if defined(CHECK_LOGIC) && CHECK_LOGIC
+ if (excl)
+ checkExcl = 0;
+
+ AtomicFetchAdd(checkIt, -1);
+#endif
+}
+
+#ifdef LIGHT
+static void* fast_thread_start(__attribute__((unused)) void* arg) {
+ for (unsigned q = 0; q < LOOPCOUNT; ++q) {
+ char excl = (RandomNumber<ui32>() % WRITELOCKS) == 0;
+ if (excl)
+ Run<TLightWriteGuard, 1>();
+ else
+ Run<TLightReadGuard, 0>();
+ }
+ return NULL;
+}
+#endif
+
+#ifdef POSIX
+static void* fast_thread_start(__attribute__((unused)) void* arg) {
+ for (unsigned q = 0; q < LOOPCOUNT; ++q) {
+ char excl = (RandomNumber<ui32>() % WRITELOCKS) == 0;
+ if (excl)
+ Run<TPosixRWExclusiveLocker, 1>();
+ else
+ Run<TPosixRWShareLocker, 0>();
+ }
+ return NULL;
+}
+#endif
+
+#ifdef RWSPINLOCK
+static void* fast_thread_start(__attribute__((unused)) void* arg) {
+ for (unsigned q = 0; q < LOOPCOUNT; ++q) {
+ char excl = (RandomNumber<ui32>() % WRITELOCKS) == 0;
+ if (excl)
+ Run<TWriteSpinLockGuard, 1>();
+ else
+ Run<TReadSpinLockGuard, 0>();
+ }
+ return NULL;
+}
+#endif
+
+int main() {
+ pthread_t threads[THREADCOUNT];
+
+ for (unsigned q = 0; q < THREADCOUNT; ++q) {
+ pthread_create(&(threads[q]), NULL, &fast_thread_start, NULL);
+ }
+
+ for (unsigned q = 0; q < THREADCOUNT; ++q)
+ pthread_join(threads[q], NULL);
+
+ return 0;
+}
+
+#else // !_linux_
+
+int main() {
+ return 0;
+}
+
+#endif
diff --git a/library/cpp/threading/light_rw_lock/bench/ya.make b/library/cpp/threading/light_rw_lock/bench/ya.make
index 7969b52a501..ed89e3a9b0a 100644
--- a/library/cpp/threading/light_rw_lock/bench/ya.make
+++ b/library/cpp/threading/light_rw_lock/bench/ya.make
@@ -1,13 +1,13 @@
-PROGRAM(lightrwlock_test)
-
-OWNER(agri)
-
-SRCS(
- lightrwlock_test.cpp
-)
-
-PEERDIR(
+PROGRAM(lightrwlock_test)
+
+OWNER(agri)
+
+SRCS(
+ lightrwlock_test.cpp
+)
+
+PEERDIR(
library/cpp/threading/light_rw_lock
-)
-
-END()
+)
+
+END()
diff --git a/library/cpp/threading/light_rw_lock/lightrwlock.cpp b/library/cpp/threading/light_rw_lock/lightrwlock.cpp
index fbb63fd47f7..58456907d2b 100644
--- a/library/cpp/threading/light_rw_lock/lightrwlock.cpp
+++ b/library/cpp/threading/light_rw_lock/lightrwlock.cpp
@@ -1,113 +1,113 @@
-#include "lightrwlock.h"
-#include <util/system/spinlock.h>
-
-#if defined(_linux_)
-
-using namespace NS_LightRWLock;
-
-void TLightRWLock::WaitForUntrappedShared() {
- for (;;) {
- for (ui32 i = 0; i < SpinCount_; ++i) {
- SpinLockPause();
-
- if ((AtomicLoad(Counter_) & 0x7FFFFFFF) == 0)
- return;
- }
-
- SequenceStore(UnshareFutex_, 1);
- if ((AtomicLoad(Counter_) & 0x7FFFFFFF) == 0) {
- AtomicStore(UnshareFutex_, 0);
- return;
- }
- FutexWait(UnshareFutex_, 1);
- }
-}
-
-void TLightRWLock::WaitForExclusiveAndUntrappedShared() {
- for (;;) {
- for (ui32 i = 0; i < SpinCount_; ++i) {
- SpinLockPause();
-
- if (AtomicLoad(Counter_) >= 0)
- goto try_to_get_lock;
- if (AtomicLoad(TrappedFutex_) == 1)
- goto skip_store_trapped;
- }
-
- SequenceStore(TrappedFutex_, 1);
- skip_store_trapped:
-
- if (AtomicLoad(Counter_) < 0) {
- FutexWait(TrappedFutex_, 1);
- }
-
- try_to_get_lock:
- if (!AtomicSetBit(Counter_, 31))
- break;
- }
-
- for (ui32 j = 0;; ++j) {
- for (ui32 i = 0; i < SpinCount_; ++i) {
- if ((AtomicLoad(Counter_) & 0x7FFFFFFF) == 0)
- return;
-
- SpinLockPause();
- }
-
- SequenceStore(UnshareFutex_, 1);
-
- if ((AtomicLoad(Counter_) & 0x7FFFFFFF) == 0) {
- AtomicStore(UnshareFutex_, 0);
- return;
- }
-
- FutexWait(UnshareFutex_, 1);
- }
-}
-
-void TLightRWLock::WaitForUntrappedAndAcquireRead() {
- if (AtomicFetchAdd(Counter_, -1) < 0)
- goto skip_lock_try;
-
- for (;;) {
- again:
- if (Y_UNLIKELY(AtomicFetchAdd(Counter_, 1) >= 0)) {
- return;
- } else {
- if (AtomicFetchAdd(Counter_, -1) >= 0)
- goto again;
- }
-
- skip_lock_try:
+#include "lightrwlock.h"
+#include <util/system/spinlock.h>
+
+#if defined(_linux_)
+
+using namespace NS_LightRWLock;
+
+void TLightRWLock::WaitForUntrappedShared() {
+ for (;;) {
+ for (ui32 i = 0; i < SpinCount_; ++i) {
+ SpinLockPause();
+
+ if ((AtomicLoad(Counter_) & 0x7FFFFFFF) == 0)
+ return;
+ }
+
+ SequenceStore(UnshareFutex_, 1);
+ if ((AtomicLoad(Counter_) & 0x7FFFFFFF) == 0) {
+ AtomicStore(UnshareFutex_, 0);
+ return;
+ }
+ FutexWait(UnshareFutex_, 1);
+ }
+}
+
+void TLightRWLock::WaitForExclusiveAndUntrappedShared() {
+ for (;;) {
+ for (ui32 i = 0; i < SpinCount_; ++i) {
+ SpinLockPause();
+
+ if (AtomicLoad(Counter_) >= 0)
+ goto try_to_get_lock;
+ if (AtomicLoad(TrappedFutex_) == 1)
+ goto skip_store_trapped;
+ }
+
+ SequenceStore(TrappedFutex_, 1);
+ skip_store_trapped:
+
+ if (AtomicLoad(Counter_) < 0) {
+ FutexWait(TrappedFutex_, 1);
+ }
+
+ try_to_get_lock:
+ if (!AtomicSetBit(Counter_, 31))
+ break;
+ }
+
+ for (ui32 j = 0;; ++j) {
+ for (ui32 i = 0; i < SpinCount_; ++i) {
+ if ((AtomicLoad(Counter_) & 0x7FFFFFFF) == 0)
+ return;
+
+ SpinLockPause();
+ }
+
+ SequenceStore(UnshareFutex_, 1);
+
+ if ((AtomicLoad(Counter_) & 0x7FFFFFFF) == 0) {
+ AtomicStore(UnshareFutex_, 0);
+ return;
+ }
+
+ FutexWait(UnshareFutex_, 1);
+ }
+}
+
+void TLightRWLock::WaitForUntrappedAndAcquireRead() {
+ if (AtomicFetchAdd(Counter_, -1) < 0)
+ goto skip_lock_try;
+
+ for (;;) {
+ again:
+ if (Y_UNLIKELY(AtomicFetchAdd(Counter_, 1) >= 0)) {
+ return;
+ } else {
+ if (AtomicFetchAdd(Counter_, -1) >= 0)
+ goto again;
+ }
+
+ skip_lock_try:
if (AtomicLoad(UnshareFutex_) && (AtomicLoad(Counter_) & 0x7FFFFFFF) == 0) {
- SequenceStore(UnshareFutex_, 0);
- FutexWake(UnshareFutex_, 1);
- }
-
- for (;;) {
- for (ui32 i = 0; i < SpinCount_; ++i) {
- SpinLockPause();
-
- if (AtomicLoad(Counter_) >= 0)
- goto again;
- if (AtomicLoad(TrappedFutex_) == 1)
- goto skip_store_trapped;
- }
-
- SequenceStore(TrappedFutex_, 1);
- skip_store_trapped:
-
- if (AtomicLoad(Counter_) < 0) {
- FutexWait(TrappedFutex_, 1);
- if (AtomicLoad(Counter_) < 0)
- goto again;
- } else if (AtomicLoad(TrappedFutex_)) {
- SequenceStore(TrappedFutex_, 0);
- FutexWake(TrappedFutex_, 0x7fffffff);
- }
- break;
- }
- }
-}
-
-#endif // _linux_
+ SequenceStore(UnshareFutex_, 0);
+ FutexWake(UnshareFutex_, 1);
+ }
+
+ for (;;) {
+ for (ui32 i = 0; i < SpinCount_; ++i) {
+ SpinLockPause();
+
+ if (AtomicLoad(Counter_) >= 0)
+ goto again;
+ if (AtomicLoad(TrappedFutex_) == 1)
+ goto skip_store_trapped;
+ }
+
+ SequenceStore(TrappedFutex_, 1);
+ skip_store_trapped:
+
+ if (AtomicLoad(Counter_) < 0) {
+ FutexWait(TrappedFutex_, 1);
+ if (AtomicLoad(Counter_) < 0)
+ goto again;
+ } else if (AtomicLoad(TrappedFutex_)) {
+ SequenceStore(TrappedFutex_, 0);
+ FutexWake(TrappedFutex_, 0x7fffffff);
+ }
+ break;
+ }
+ }
+}
+
+#endif // _linux_
diff --git a/library/cpp/threading/light_rw_lock/lightrwlock.h b/library/cpp/threading/light_rw_lock/lightrwlock.h
index 931a1817bce..44117871695 100644
--- a/library/cpp/threading/light_rw_lock/lightrwlock.h
+++ b/library/cpp/threading/light_rw_lock/lightrwlock.h
@@ -1,45 +1,45 @@
-#pragma once
+#pragma once
-#include <util/system/rwlock.h>
+#include <util/system/rwlock.h>
#include <util/system/sanitizers.h>
-
-#if defined(_linux_)
-/* TLightRWLock is optimized for read lock and very fast lock/unlock switching.
- Read lock increments counter.
- Write lock sets highest bit of counter (makes counter negative).
-
- Whenever a thread tries to acquire read lock that thread increments
- the counter. If the thread gets negative value of the counter right just
- after the increment that means write lock was acquired in another thread.
- In that case the thread decrements the counter back, wakes one thread on
- UnshareFutex, waits on the TrappedFutex and then tries acquire read lock
- from the beginning.
- If the thread gets positive value of the counter after the increment
- then read lock was successfully acquired and
- the thread can proceed execution.
-
- Whenever a thread tries to acquire write lock that thread set the highest bit
- of the counter. If the thread determine that the bit was set previously then
- write lock was acquired in another thread. In that case the thread waits on
- the TrappedFutex and then tries again from the beginning.
- If the highest bit was successfully set then thread check if any read lock
- exists at the moment. If so the thread waits on UnshareFutex. If there is
- no more read locks then write lock was successfully acquired and the thread
- can proceed execution.
-*/
-
-#include <linux/futex.h>
+
+#if defined(_linux_)
+/* TLightRWLock is optimized for read lock and very fast lock/unlock switching.
+ Read lock increments counter.
+ Write lock sets highest bit of counter (makes counter negative).
+
+ Whenever a thread tries to acquire read lock that thread increments
+ the counter. If the thread gets negative value of the counter right just
+ after the increment that means write lock was acquired in another thread.
+ In that case the thread decrements the counter back, wakes one thread on
+ UnshareFutex, waits on the TrappedFutex and then tries acquire read lock
+ from the beginning.
+ If the thread gets positive value of the counter after the increment
+ then read lock was successfully acquired and
+ the thread can proceed execution.
+
+ Whenever a thread tries to acquire write lock that thread set the highest bit
+ of the counter. If the thread determine that the bit was set previously then
+ write lock was acquired in another thread. In that case the thread waits on
+ the TrappedFutex and then tries again from the beginning.
+ If the highest bit was successfully set then thread check if any read lock
+ exists at the moment. If so the thread waits on UnshareFutex. If there is
+ no more read locks then write lock was successfully acquired and the thread
+ can proceed execution.
+*/
+
+#include <linux/futex.h>
#include <unistd.h>
-#include <sys/syscall.h>
-#include <errno.h>
-
-namespace NS_LightRWLock {
+#include <sys/syscall.h>
+#include <errno.h>
+
+namespace NS_LightRWLock {
static int Y_FORCE_INLINE AtomicFetchAdd(volatile int& item, int value) {
return __atomic_fetch_add(&item, value, __ATOMIC_SEQ_CST);
}
-
-#if defined(_x86_64_) || defined(_i386_)
-
+
+#if defined(_x86_64_) || defined(_i386_)
+
static char Y_FORCE_INLINE AtomicSetBit(volatile int& item, unsigned bit) {
char ret;
__asm__ __volatile__(
@@ -54,7 +54,7 @@ namespace NS_LightRWLock {
return ret;
}
-
+
static char Y_FORCE_INLINE AtomicClearBit(volatile int& item, unsigned bit) {
char ret;
__asm__ __volatile__(
@@ -69,22 +69,22 @@ namespace NS_LightRWLock {
return ret;
}
-
-
-#else
-
+
+
+#else
+
static char Y_FORCE_INLINE AtomicSetBit(volatile int& item, unsigned bit) {
int prev = __atomic_fetch_or(&item, 1 << bit, __ATOMIC_SEQ_CST);
return (prev & (1 << bit)) != 0 ? 1 : 0;
}
-
+
static char Y_FORCE_INLINE
AtomicClearBit(volatile int& item, unsigned bit) {
int prev = __atomic_fetch_and(&item, ~(1 << bit), __ATOMIC_SEQ_CST);
return (prev & (1 << bit)) != 0 ? 1 : 0;
}
#endif
-
+
#if defined(_x86_64_) || defined(_i386_) || defined (__aarch64__) || defined (__powerpc64__)
static bool AtomicLockHighByte(volatile int& item) {
union TA {
@@ -98,23 +98,23 @@ namespace NS_LightRWLock {
__ATOMIC_SEQ_CST, __ATOMIC_RELAXED);
}
-#endif
-
+#endif
+
template <typename TInt>
static void Y_FORCE_INLINE AtomicStore(volatile TInt& var, TInt value) {
__atomic_store_n(&var, value, __ATOMIC_RELEASE);
}
-
+
template <typename TInt>
static void Y_FORCE_INLINE SequenceStore(volatile TInt& var, TInt value) {
__atomic_store_n(&var, value, __ATOMIC_SEQ_CST);
}
-
+
template <typename TInt>
static TInt Y_FORCE_INLINE AtomicLoad(const volatile TInt& var) {
return __atomic_load_n(&var, __ATOMIC_ACQUIRE);
}
-
+
static void Y_FORCE_INLINE FutexWait(volatile int& fvar, int value) {
for (;;) {
int result =
@@ -126,9 +126,9 @@ namespace NS_LightRWLock {
continue;
Y_FAIL("futex error");
}
- }
- }
-
+ }
+ }
+
static void Y_FORCE_INLINE FutexWake(volatile int& fvar, int amount) {
const int result =
syscall(SYS_futex, &fvar, FUTEX_WAKE_PRIVATE, amount, NULL, NULL, 0);
@@ -136,85 +136,85 @@ namespace NS_LightRWLock {
Y_FAIL("futex error");
}
-}
-
-class alignas(64) TLightRWLock {
-public:
- TLightRWLock(ui32 spinCount = 10)
- : Counter_(0)
- , TrappedFutex_(0)
- , UnshareFutex_(0)
- , SpinCount_(spinCount)
+}
+
+class alignas(64) TLightRWLock {
+public:
+ TLightRWLock(ui32 spinCount = 10)
+ : Counter_(0)
+ , TrappedFutex_(0)
+ , UnshareFutex_(0)
+ , SpinCount_(spinCount)
{
}
-
- TLightRWLock(const TLightRWLock&) = delete;
- void operator=(const TLightRWLock&) = delete;
-
- Y_FORCE_INLINE void AcquireWrite() {
- using namespace NS_LightRWLock;
-
- if (AtomicLockHighByte(Counter_)) {
- if ((AtomicLoad(Counter_) & 0x7FFFFFFF) == 0)
- return;
- return WaitForUntrappedShared();
- }
- WaitForExclusiveAndUntrappedShared();
- }
-
- Y_FORCE_INLINE void AcquireRead() {
- using namespace NS_LightRWLock;
-
- if (Y_LIKELY(AtomicFetchAdd(Counter_, 1) >= 0))
- return;
- WaitForUntrappedAndAcquireRead();
- }
-
- Y_FORCE_INLINE void ReleaseWrite() {
- using namespace NS_LightRWLock;
-
- AtomicClearBit(Counter_, 31);
- if (AtomicLoad(TrappedFutex_)) {
- SequenceStore(TrappedFutex_, 0);
- FutexWake(TrappedFutex_, 0x7fffffff);
- }
- }
-
- Y_FORCE_INLINE void ReleaseRead() {
- using namespace NS_LightRWLock;
-
- if (Y_LIKELY(AtomicFetchAdd(Counter_, -1) >= 0))
- return;
- if (!AtomicLoad(UnshareFutex_))
- return;
- if ((AtomicLoad(Counter_) & 0x7fffffff) == 0) {
- SequenceStore(UnshareFutex_, 0);
- FutexWake(UnshareFutex_, 1);
- }
- }
-
-private:
- volatile int Counter_;
- volatile int TrappedFutex_;
- volatile int UnshareFutex_;
- const ui32 SpinCount_;
-
- void WaitForUntrappedShared();
- void WaitForExclusiveAndUntrappedShared();
- void WaitForUntrappedAndAcquireRead();
-};
-
-#else
-
-class TLightRWLock: public TRWMutex {
-public:
+
+ TLightRWLock(const TLightRWLock&) = delete;
+ void operator=(const TLightRWLock&) = delete;
+
+ Y_FORCE_INLINE void AcquireWrite() {
+ using namespace NS_LightRWLock;
+
+ if (AtomicLockHighByte(Counter_)) {
+ if ((AtomicLoad(Counter_) & 0x7FFFFFFF) == 0)
+ return;
+ return WaitForUntrappedShared();
+ }
+ WaitForExclusiveAndUntrappedShared();
+ }
+
+ Y_FORCE_INLINE void AcquireRead() {
+ using namespace NS_LightRWLock;
+
+ if (Y_LIKELY(AtomicFetchAdd(Counter_, 1) >= 0))
+ return;
+ WaitForUntrappedAndAcquireRead();
+ }
+
+ Y_FORCE_INLINE void ReleaseWrite() {
+ using namespace NS_LightRWLock;
+
+ AtomicClearBit(Counter_, 31);
+ if (AtomicLoad(TrappedFutex_)) {
+ SequenceStore(TrappedFutex_, 0);
+ FutexWake(TrappedFutex_, 0x7fffffff);
+ }
+ }
+
+ Y_FORCE_INLINE void ReleaseRead() {
+ using namespace NS_LightRWLock;
+
+ if (Y_LIKELY(AtomicFetchAdd(Counter_, -1) >= 0))
+ return;
+ if (!AtomicLoad(UnshareFutex_))
+ return;
+ if ((AtomicLoad(Counter_) & 0x7fffffff) == 0) {
+ SequenceStore(UnshareFutex_, 0);
+ FutexWake(UnshareFutex_, 1);
+ }
+ }
+
+private:
+ volatile int Counter_;
+ volatile int TrappedFutex_;
+ volatile int UnshareFutex_;
+ const ui32 SpinCount_;
+
+ void WaitForUntrappedShared();
+ void WaitForExclusiveAndUntrappedShared();
+ void WaitForUntrappedAndAcquireRead();
+};
+
+#else
+
+class TLightRWLock: public TRWMutex {
+public:
TLightRWLock() {
}
TLightRWLock(ui32) {
}
-};
-
-#endif
-
-using TLightReadGuard = TReadGuardBase<TLightRWLock>;
-using TLightWriteGuard = TWriteGuardBase<TLightRWLock>;
+};
+
+#endif
+
+using TLightReadGuard = TReadGuardBase<TLightRWLock>;
+using TLightWriteGuard = TWriteGuardBase<TLightRWLock>;
diff --git a/library/cpp/threading/light_rw_lock/ut/rwlock_ut.cpp b/library/cpp/threading/light_rw_lock/ut/rwlock_ut.cpp
index e82063d959f..3ed4bf68faa 100644
--- a/library/cpp/threading/light_rw_lock/ut/rwlock_ut.cpp
+++ b/library/cpp/threading/light_rw_lock/ut/rwlock_ut.cpp
@@ -1,122 +1,122 @@
#include <library/cpp/threading/light_rw_lock/lightrwlock.h>
#include <library/cpp/testing/unittest/registar.h>
-#include <util/random/random.h>
-#include <util/system/atomic.h>
+#include <util/random/random.h>
+#include <util/system/atomic.h>
#include <util/thread/pool.h>
-
-class TRWMutexTest: public TTestBase {
- UNIT_TEST_SUITE(TRWMutexTest);
- UNIT_TEST(TestReaders)
- UNIT_TEST(TestReadersWriters)
- UNIT_TEST_SUITE_END();
-
- struct TSharedData {
- TSharedData()
- : writersIn(0)
- , readersIn(0)
- , failed(false)
- {
- }
-
- TAtomic writersIn;
- TAtomic readersIn;
-
- bool failed;
-
- TLightRWLock mutex;
- };
-
- class TThreadTask: public IObjectInQueue {
- public:
- using PFunc = void (TThreadTask::*)(void);
-
- TThreadTask(PFunc func, TSharedData& data, size_t id, size_t total)
- : Func_(func)
- , Data_(data)
- , Id_(id)
- , Total_(total)
- {
- }
-
- void Process(void*) override {
- THolder<TThreadTask> This(this);
-
- (this->*Func_)();
- }
-
-#define FAIL_ASSERT(cond) \
- if (!(cond)) { \
- Data_.failed = true; \
- }
- void RunReaders() {
- Data_.mutex.AcquireRead();
-
- AtomicIncrement(Data_.readersIn);
- usleep(100);
- FAIL_ASSERT(Data_.readersIn == long(Total_));
- usleep(100);
- AtomicDecrement(Data_.readersIn);
-
- Data_.mutex.ReleaseRead();
- }
-
- void RunReadersWriters() {
- if (Id_ % 2 == 0) {
- for (size_t i = 0; i < 10; ++i) {
- Data_.mutex.AcquireRead();
-
- AtomicIncrement(Data_.readersIn);
- FAIL_ASSERT(Data_.writersIn == 0);
- usleep(RandomNumber<ui32>() % 5);
- AtomicDecrement(Data_.readersIn);
-
- Data_.mutex.ReleaseRead();
- }
- } else {
- for (size_t i = 0; i < 10; ++i) {
- Data_.mutex.AcquireWrite();
-
- AtomicIncrement(Data_.writersIn);
- FAIL_ASSERT(Data_.readersIn == 0 && Data_.writersIn == 1);
- usleep(RandomNumber<ui32>() % 5);
- AtomicDecrement(Data_.writersIn);
-
- Data_.mutex.ReleaseWrite();
- }
- }
- }
-#undef FAIL_ASSERT
-
- private:
- PFunc Func_;
- TSharedData& Data_;
- size_t Id_;
- size_t Total_;
- };
-
-private:
-#define RUN_CYCLE(what, count) \
- Q_.Start(count); \
- for (size_t i = 0; i < count; ++i) { \
- UNIT_ASSERT(Q_.Add(new TThreadTask(&TThreadTask::what, Data_, i, count))); \
- } \
- Q_.Stop(); \
- bool b = Data_.failed; \
- Data_.failed = false; \
- UNIT_ASSERT(!b);
-
- void TestReaders() {
- RUN_CYCLE(RunReaders, 1);
- }
-
- void TestReadersWriters() {
- RUN_CYCLE(RunReadersWriters, 1);
- }
-
-#undef RUN_CYCLE
-private:
- TSharedData Data_;
+
+class TRWMutexTest: public TTestBase {
+ UNIT_TEST_SUITE(TRWMutexTest);
+ UNIT_TEST(TestReaders)
+ UNIT_TEST(TestReadersWriters)
+ UNIT_TEST_SUITE_END();
+
+ struct TSharedData {
+ TSharedData()
+ : writersIn(0)
+ , readersIn(0)
+ , failed(false)
+ {
+ }
+
+ TAtomic writersIn;
+ TAtomic readersIn;
+
+ bool failed;
+
+ TLightRWLock mutex;
+ };
+
+ class TThreadTask: public IObjectInQueue {
+ public:
+ using PFunc = void (TThreadTask::*)(void);
+
+ TThreadTask(PFunc func, TSharedData& data, size_t id, size_t total)
+ : Func_(func)
+ , Data_(data)
+ , Id_(id)
+ , Total_(total)
+ {
+ }
+
+ void Process(void*) override {
+ THolder<TThreadTask> This(this);
+
+ (this->*Func_)();
+ }
+
+#define FAIL_ASSERT(cond) \
+ if (!(cond)) { \
+ Data_.failed = true; \
+ }
+ void RunReaders() {
+ Data_.mutex.AcquireRead();
+
+ AtomicIncrement(Data_.readersIn);
+ usleep(100);
+ FAIL_ASSERT(Data_.readersIn == long(Total_));
+ usleep(100);
+ AtomicDecrement(Data_.readersIn);
+
+ Data_.mutex.ReleaseRead();
+ }
+
+ void RunReadersWriters() {
+ if (Id_ % 2 == 0) {
+ for (size_t i = 0; i < 10; ++i) {
+ Data_.mutex.AcquireRead();
+
+ AtomicIncrement(Data_.readersIn);
+ FAIL_ASSERT(Data_.writersIn == 0);
+ usleep(RandomNumber<ui32>() % 5);
+ AtomicDecrement(Data_.readersIn);
+
+ Data_.mutex.ReleaseRead();
+ }
+ } else {
+ for (size_t i = 0; i < 10; ++i) {
+ Data_.mutex.AcquireWrite();
+
+ AtomicIncrement(Data_.writersIn);
+ FAIL_ASSERT(Data_.readersIn == 0 && Data_.writersIn == 1);
+ usleep(RandomNumber<ui32>() % 5);
+ AtomicDecrement(Data_.writersIn);
+
+ Data_.mutex.ReleaseWrite();
+ }
+ }
+ }
+#undef FAIL_ASSERT
+
+ private:
+ PFunc Func_;
+ TSharedData& Data_;
+ size_t Id_;
+ size_t Total_;
+ };
+
+private:
+#define RUN_CYCLE(what, count) \
+ Q_.Start(count); \
+ for (size_t i = 0; i < count; ++i) { \
+ UNIT_ASSERT(Q_.Add(new TThreadTask(&TThreadTask::what, Data_, i, count))); \
+ } \
+ Q_.Stop(); \
+ bool b = Data_.failed; \
+ Data_.failed = false; \
+ UNIT_ASSERT(!b);
+
+ void TestReaders() {
+ RUN_CYCLE(RunReaders, 1);
+ }
+
+ void TestReadersWriters() {
+ RUN_CYCLE(RunReadersWriters, 1);
+ }
+
+#undef RUN_CYCLE
+private:
+ TSharedData Data_;
TThreadPool Q_;
-};
-
-UNIT_TEST_SUITE_REGISTRATION(TRWMutexTest)
+};
+
+UNIT_TEST_SUITE_REGISTRATION(TRWMutexTest)
diff --git a/library/cpp/threading/light_rw_lock/ut/ya.make b/library/cpp/threading/light_rw_lock/ut/ya.make
index 92928b837c2..9b1a54d7ecd 100644
--- a/library/cpp/threading/light_rw_lock/ut/ya.make
+++ b/library/cpp/threading/light_rw_lock/ut/ya.make
@@ -1,9 +1,9 @@
UNITTEST_FOR(library/cpp/threading/light_rw_lock)
-
+
OWNER(agri)
-
-SRCS(
- rwlock_ut.cpp
-)
-
-END()
+
+SRCS(
+ rwlock_ut.cpp
+)
+
+END()
diff --git a/library/cpp/threading/light_rw_lock/ya.make b/library/cpp/threading/light_rw_lock/ya.make
index a196fb85886..e86fd422238 100644
--- a/library/cpp/threading/light_rw_lock/ya.make
+++ b/library/cpp/threading/light_rw_lock/ya.make
@@ -1,10 +1,10 @@
-LIBRARY()
-
-OWNER(agri)
-
-SRCS(
- lightrwlock.cpp
- lightrwlock.h
-)
-
-END()
+LIBRARY()
+
+OWNER(agri)
+
+SRCS(
+ lightrwlock.cpp
+ lightrwlock.h
+)
+
+END()