#include #include #ifdef _linux_ // Light rw lock is implemented only for linux using namespace NS_LightRWLock; #include #include #include #define LIGHT #ifdef RWSPINLOCK #include #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 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(); #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() % WRITELOCKS) == 0; if (excl) Run(); else Run(); } return NULL; } #endif #ifdef POSIX static void* fast_thread_start(__attribute__((unused)) void* arg) { for (unsigned q = 0; q < LOOPCOUNT; ++q) { char excl = (RandomNumber() % WRITELOCKS) == 0; if (excl) Run(); else Run(); } return NULL; } #endif #ifdef RWSPINLOCK static void* fast_thread_start(__attribute__((unused)) void* arg) { for (unsigned q = 0; q < LOOPCOUNT; ++q) { char excl = (RandomNumber() % WRITELOCKS) == 0; if (excl) Run(); else Run(); } 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