FastReadersWriterLock (object)¶
Implement a readers-writer lock, with active waiting and priority management (0 = highest .. 3 = lowest). In order to be active, priority management must be initially enabled with FastReadersWriterLock.enableWritePriorities.
Guaranties are as follow:
- Locks are reentrant: a reader can nest a writer or reader lock, and vice versa
- Readers will wait for writers to finish, unless they have been waiting longer than these, or reader’s thread has higher priority than writers (synchronous VS asynchronous - AsyncTaskQueue)
- Writers will wait for readers to finish
- Writers will let yield to other queued writers with higher priority
- If an active reader requests a write lock, this write will happen before any other writes of lower priority
- If a reader requests a write of lower priority, other writes of equal or higher priority could happen first
The logic is read-biased for speed of access when no writers, but write-biased for access priority. Going from read to write is allowed, but it doesn’t garantee that other writes might happen in-between (which is the case anyway since all readers could in theory ask to upgrade to write at the same time).
For the control, we’re using one main atomic UInt32 which as 2 parts:
- “how many are waiting to write or currently writing”
- “some reads might be happening or have happened recently” (one bit)
Then, we use a “readDepth” and “writeDepth” per thread (allows, too, reentrency within a same thread).
This allows the following optimizations.
- New readers set their “readDepth” to 1. Then, in one atomic operation, the readers get A) and set B).
If no A), they go straight to their reading. If there is some A), they yield (set put back their “readDepth” to 0 and wait for no writers).
- In one atomic operation, new writers increment A) and get B). They then wait to get the write lock.
Once a writer has the write lock, they check if there might be concurrent readers by fetching B) (and it clears B at the same time). If not, they go straight to write. Otherwise, it will actively wait for readers to finish by looping over their “readDepth”, until they are all done.
Members¶
FastReadersWriterLock_perThreadStates[] | perThreadStates | |
UInt32 | waitingWritersCountAndSomeMightReadBit | |
Ref<AsyncTaskQueue> | asyncTaskQueue | |
UInt32 | parallelWritingAllowedDepth | |
LightLock | writeLock | |
String | name | |
UInt32 | nextRequestOrder | |
UInt32 | nextWaitingReaderOrder | |
UInt32 | nextWaitingWriterOrder | |
Boolean | prioritiesEnabled | |
UInt32 | waitingPrioritiesBits | |
UInt32[8] | perPriorityCounts | |
UInt8 | writerWaitingWriterForReaders | |
UInt32 | debugCount |
Methods¶
FastReadersWriterLock ( in FastReadersWriterLock other ) | |
FastReadersWriterLock ( in String name ) | |
FastReadersWriterLock () | |
Boolean | acquireRead ? ( in UInt32 threadIndex ) |
Boolean | acquireRead ? () |
Boolean | acquireWrite ? ( in UInt32 priority ) |
Boolean | acquireWrite ? ( in UInt32 threadIndex, in UInt32 priority ) |
Boolean | acquireWrite ? () |
FastReadersWriterLock | clone ? () |
Boolean | currentThreadHasWriteLock ? () |
enableWritePriorities ! () | |
init ! ( in String name ) | |
Boolean | isParallelWritingAllowed ? () |
Boolean | readLockedByCurrentThread ? () |
Boolean | readLocked_slow ? ( in Boolean excludeThisThread ) |
Boolean | readLocked_slow ? ( in Boolean excludeThisThread, io FastReadersWriterLock_perThreadStates offending, io UInt32 offendingIndex ) |
releaseLocksBeforeThrow ? () | |
releaseRead ? ( in UInt32 threadIndex ) | |
releaseRead ? () | |
releaseWrite ? ( in UInt32 threadIndex ) | |
releaseWrite ? () | |
Boolean | writeLocked ? () |
Boolean | writeLockedByCurrentThread ? () |
Boolean | writeLocked_fetch ? () |
Methods in detail¶
FastReadersWriterLock ( in FastReadersWriterLock other )
copy constructor
FastReadersWriterLock ( in String name )
Boolean FastReadersWriterLock.acquireRead? ( in UInt32 threadIndex )
Boolean FastReadersWriterLock.acquireRead? ()
Boolean FastReadersWriterLock.acquireWrite? ( in UInt32 priority )
Boolean FastReadersWriterLock.acquireWrite? ( in UInt32 threadIndex, in UInt32 priority )
(“Release lock prio=”+priority+” mask=”+priorityMask+” current=”+(waitingPriorities & priorityMask));
Boolean FastReadersWriterLock.acquireWrite? ()
FastReadersWriterLock FastReadersWriterLock.clone? ()
clone method
Boolean FastReadersWriterLock.currentThreadHasWriteLock? ()
Returns true if the current thread has a write lock.
FastReadersWriterLock.enableWritePriorities! ()
FastReadersWriterLock.init! ( in String name )
Boolean FastReadersWriterLock.isParallelWritingAllowed? ()
Parallel writing can only be allowed explicitly through a MultithreadReadersWriterLockBracket / ThreadReadersWriterLockBracket construct
Boolean FastReadersWriterLock.readLockedByCurrentThread? ()
Boolean FastReadersWriterLock.readLocked_slow? ( in Boolean excludeThisThread )
Boolean FastReadersWriterLock.readLocked_slow? ( in Boolean excludeThisThread, io FastReadersWriterLock_perThreadStates offending, io UInt32 offendingIndex )
FastReadersWriterLock.releaseLocksBeforeThrow? ()
FastReadersWriterLock.releaseRead? ( in UInt32 threadIndex )
FastReadersWriterLock.releaseRead? ()
FastReadersWriterLock.releaseWrite? ( in UInt32 threadIndex )
FastReadersWriterLock.releaseWrite? ()
Boolean FastReadersWriterLock.writeLocked? ()
Boolean FastReadersWriterLock.writeLockedByCurrentThread? ()
Boolean FastReadersWriterLock.writeLocked_fetch? ()