Cpp Utilities 1.2.3
|
ReadWrite lock using spin_lock, copied from Folly library under Apache-2.0 license, see https://github.com/facebook/folly/blob/master/folly/synchronization/RWSpinLock.h. More...
Go to the source code of this file.
Classes | |
class | Memory::RWSpinLock |
High-performance read-write-spinlock, see RWSpinLock.hpp for details. More... | |
class | Memory::RWSpinLock::ReadHolder |
RAII guard for read lock with RWSpinLock::lock_shared() on construction and RWSpinLock::unlock_shared() on destruction. More... | |
class | Memory::RWSpinLock::UpgradedHolder |
RAII guard for upgrade lock with RWSpinLock::lock_upgrade() on construction and RWSpinLock::unlock_upgrade() on destruction. More... | |
class | Memory::RWSpinLock::WriteHolder |
RAII guard for write lock with RWSpinLock::lock() on construction and RWSpinLock::unlock() on destruction. More... | |
Namespaces | |
namespace | Memory |
Namespace for all classes, typedefs and functions of memory safety. See Memory Safety for more instrucion. | |
ReadWrite lock using spin_lock, copied from Folly library under Apache-2.0 license, see https://github.com/facebook/folly/blob/master/folly/synchronization/RWSpinLock.h.
N.B. You most likely do not want to use RWSpinLock or any other kind of spinlock. Use SharedMutex instead.
In short, spinlocks in preemptive multi-tasking operating systems have serious problems and fast mutexes like SharedMutex are almost certainly the better choice, because letting the OS scheduler put a thread to sleep is better for system responsiveness and throughput than wasting a timeslice repeatedly querying a lock held by a thread that's blocked, and you can't prevent userspace programs blocking.
Spinlocks in an operating system kernel make much more sense than they do in userspace.
Read-Write spin lock implementations.
Ref: http://locklessinc.com/articles/locks
Both locks here are faster than pthread_rwlock and have very low overhead (usually 20-30ns). They don't use any system mutexes and are very compact (4/8 bytes), so are suitable for per-instance based locking, particularly when contention is not expected.
For a spinlock, RWSpinLock is a reasonable choice. (See the note about for why a spin lock is frequently a bad idea generally.) RWSpinLock has minimal overhead, and comparable contention performance when the number of competing threads is less than or equal to the number of logical CPUs. Even as the number of threads gets larger, RWSpinLock can still be very competitive in READ, although it is slower on WRITE, and also inherently unfair to writers.
The lock will not grant any new shared (read) accesses while a thread attempting to acquire the lock in write mode is blocked. (That is, if the lock is held in shared mode by N threads, and a thread attempts to acquire it in write mode, no one else can acquire it in shared mode until these N threads release the lock and then the blocked thread acquires and releases the exclusive lock.) This also applies for attempts to reacquire the lock in shared mode by threads that already hold it in shared mode, making the lock non-reentrant.
RWSpinLock handles 2^30 - 1 concurrent readers.
Benchmark on (Intel(R) Xeon(R) CPU L5630 @ 2.13GHz) 8 cores(16 HTs)
Benchmark | Iters | Total t | t/iter | iter/sec |
---|---|---|---|---|
* BM_RWSpinLockRead | 100000 | 1.786 ms | 17.86 ns | 53.4 M |
+30.5% BM_RWSpinLockWrite | 100000 | 2.331 ms | 23.31 ns | 40.91 M |
+ 175% BM_PThreadRWMutexRead | 100000 | 4.917 ms | 49.17 ns | 19.4 M |
+ 166% BM_PThreadRWMutexWrite | 100000 | 4.757 ms | 47.57 ns | 20.05 M |
Benchmark | hits | average | min | max | sigma |
---|---|---|---|---|---|
8 threads | |||||
RWSpinLock Write | 142666 | 220 ns | 78 ns | 40.8 us | 269 ns |
RWSpinLock Read | 1282297 | 222 ns | 80 ns | 37.7 us | 248 ns |
pthread_rwlock_t Write | 84248 | 2.48 us | 99 ns | 269 us | 8.19 us |
pthread_rwlock_t Read | 761646 | 933 ns | 101 ns | 374 us | 3.25 us |
16 threads | |||||
RWSpinLock Write | 124236 | 237 ns | 78 ns | 261 us | 801 ns |
RWSpinLock Read | 1115807 | 236 ns | 78 ns | 2.27 ms | 2.17 us |
pthread_rwlock_t Write | 83363 | 7.12 us | 99 ns | 785 us | 28.1 us |
pthread_rwlock_t Read | 754978 | 2.18 us | 101 ns | 1.02 ms | 14.3 us |
50 threads | |||||
RWSpinLock Write | 131142 | 1.37 us | 82 ns | 7.53 ms | 68.2 us |
RWSpinLock Read | 1181240 | 262 ns | 78 ns | 6.62 ms | 12.7 us |
pthread_rwlock_t Write | 80849 | 112 us | 103 ns | 4.52 ms | 263 us |
pthread_rwlock_t Read | 728698 | 24 us | 101 ns | 7.28 ms | 194 us |