class rw_spin_lock { public: rw_spin_lock() { _readers = 0; } public: void acquire_reader() { int retry = 0; while (true) { uint32_t prev_readers = _readers; if (prev_readers != HAS_WRITER) { uint32_t new_readers = prev_readers + 1; if (_readers.compare_exchange_weak(prev_readers, new_readers)) { // we've won the race return; } } retry++; if (retry > RETRY_THRESHOLD) { retry = 0; this_thread::yield(); } } } void release_reader() { int retry = 0; while (true) { uint32_t prev_readers = _readers; if (prev_readers != HAS_WRITER && prev_readers > 0) { uint32_t new_readers = prev_readers - 1; if (_readers.compare_exchange_weak(prev_readers, new_readers)) { // we've won the race return; } } retry++; if (retry > RETRY_THRESHOLD) { retry = 0; this_thread::yield(); } } } void acquire_writer() { int retry = 0; while (true) { uint32_t prev_readers = _readers; if (prev_readers == 0) { if (_readers.compare_exchange_weak(prev_readers, HAS_WRITER)) { // we've won the race return; } } retry++; if (retry > RETRY_THRESHOLD) { // save some cpu cycles retry = 0; this_thread::yield(); } } } void release_writer() { int retry = 0; while (true) { uint32_t prev_readers = _readers; if (prev_readers == HAS_WRITER) { if (_readers.compare_exchange_weak(prev_readers, 0)) { // we've won the race return; } } retry++; if (retry > RETRY_THRESHOLD) { // save some cpu cycles retry = 0; this_thread::yield(); } } } private: const uint32_t HAS_WRITER = 0xffffffff; const int RETRY_THRESHOLD = 100; std::atomic _readers; }; class reader_lock { public: reader_lock(rw_spin_lock &lock) : _lock(lock) { _lock.acquire_reader(); } ~reader_lock() { _lock.release_reader(); } private: rw_spin_lock &_lock; }; class writer_lock { public: writer_lock(rw_spin_lock &lock) : _lock(lock) { _lock.acquire_writer(); } ~writer_lock() { _lock.release_writer(); } private: rw_spin_lock &_lock; };