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:

  1. “how many are waiting to write or currently writing”
  2. “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.

FastReadersWriterLock FastReadersWriterLock FastReadersWriterLock

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 )


FastReadersWriterLock ()


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? ()