Class WriterReaderPhaser
- java.lang.Object
-
- org.HdrHistogram.WriterReaderPhaser
-
public class WriterReaderPhaser extends Object
A WriterReaderPhaser
WriterReaderPhaserprovides an asymmetric means for synchronizing the execution of wait-free "writer" critical sections against a "reader phase flip" that needs to make sure no writer critical sections that were active at the beginning of the flip are still active after the flip is done. Multiple writers and multiple readers are supported.Using a
WriterReaderPhaserfor coordination, writers can continuously perform wait-free/lock-free updates to common data structures, while readers can get hold of atomic and inactive snapshots without stalling writers.While a
WriterReaderPhasercan be useful in multiple scenarios, a specific and common use case is that of safely managing "double buffered" data stream access in which writers can proceed without being blocked, while readers gain access to stable and unchanging buffer samples.WriterReaderPhaser"writers" are wait free (on architectures that support wait free atomic increment operations), "readers" block for other "readers", and "readers" are only blocked by "writers" whose critical section was entered before the reader'sflipPhase()attempt.Assumptions and Guarantees
When used to protect an actively recording data structure, the assumptions on how readers and writers act are:
- There are two sets of data structures ("active" and "inactive")
- Writing is done to the perceived active version (as perceived by the
writer), and only within critical sections delineated by
writerCriticalSectionEnter()andwriterCriticalSectionExit(). - Only readers switch the perceived roles of the active and inactive data
structures. They do so only while under
readerLock()protection and only before callingflipPhase(). - Writers do not remain in their critical sections indefinitely.
- Only writers perform
writerCriticalSectionEnter()andwriterCriticalSectionExit(). - Readers do not hold onto readerLock indefinitely.
- Only readers perform
readerLock()andreaderUnlock(). - Only readers perform
flipPhase()operations, and only while holding the readerLock.
When the above assumptions are met,
WriterReaderPhaserguarantees that the inactive data structures are not being modified by any writers while being read while under readerLock() protection after aflipPhase()() operation.The following progress guarantees are provided to writers and readers that adhere to the above stated assumptions:
- Writers operations
(
writerCriticalSectionEnterandwriterCriticalSectionExit) are wait free on architectures that support wait-free atomic increment operations (they remain lock-free [but not wait-free] on architectures that do not support wait-free atomic increment operations) flipPhase()operations are guaranteed to make forward progress, and will only be blocked by writers whose critical sections were entered prior to the start of the reader's flipPhase operation, and have not yet exited their critical sections.readerLock()only blocks for other readers that are holding the readerLock.
Example use
Imagine a simple use case where a histogram (which is basically a large set of rapidly updated counters) is being modified by writers, and a reader needs to gain access to stable interval samples of the histogram for reporting or other analysis purposes.
A writer may record values the histogram:final WriterReaderPhaser recordingPhaser = new WriterReaderPhaser(); volatile Histogram activeHistogram; Histogram inactiveHistogram; ...
A reader gains access to a stable histogram of values recorded during an interval, and reports on it:// Wait-free recording: long criticalValueAtEnter = recordingPhaser.writerCriticalSectionEnter(); try { activeHistogram.recordValue(value); } finally { recordingPhaser.writerCriticalSectionExit(criticalValueAtEnter); }try { recordingPhaser.readerLock(); inactiveHistogram.reset(); // Swap active and inactive histograms: final Histogram tempHistogram = inactiveHistogram; inactiveHistogram = activeHistogram; activeHistogram = tempHistogram; recordingPhaser.flipPhase(); // At this point, inactiveHistogram content is guaranteed to be stable logHistogram(inactiveHistogram); } finally { recordingPhaser.readerUnlock(); }
-
-
Constructor Summary
Constructors Constructor Description WriterReaderPhaser()
-
Method Summary
All Methods Instance Methods Concrete Methods Modifier and Type Method Description voidflipPhase()Flip a phase in theWriterReaderPhaserinstance,flipPhase()can only be called while holding thereaderLock.voidflipPhase(long yieldTimeNsec)Flip a phase in theWriterReaderPhaserinstance,flipPhase()can only be called while holding thereaderLock.voidreaderLock()Enter to a critical section containing a read operation (reentrant, mutually excludes againstreaderLockcalls by other threads).voidreaderUnlock()Exit from a critical section containing a read operation (relinquishes mutual exclusion against otherreaderLockcalls).longwriterCriticalSectionEnter()Indicate entry to a critical section containing a write operation.voidwriterCriticalSectionExit(long criticalValueAtEnter)Indicate exit from a critical section containing a write operation.
-
-
-
Method Detail
-
writerCriticalSectionEnter
public long writerCriticalSectionEnter()
Indicate entry to a critical section containing a write operation.This call is wait-free on architectures that support wait free atomic increment operations, and is lock-free on architectures that do not.
writerCriticalSectionEnter()must be matched with a subsequentwriterCriticalSectionExit(long)in order for CriticalSectionPhaser synchronization to function properly.- Returns:
- an (opaque) value associated with the critical section entry, which MUST be provided
to the matching
writerCriticalSectionExit(long)call.
-
writerCriticalSectionExit
public void writerCriticalSectionExit(long criticalValueAtEnter)
Indicate exit from a critical section containing a write operation.This call is wait-free on architectures that support wait free atomic increment operations, and is lock-free on architectures that do not.
writerCriticalSectionExit(long)must be matched with a precedingwriterCriticalSectionEnter()call, and must be provided with the matchingwriterCriticalSectionEnter()call's return value, in order for CriticalSectionPhaser synchronization to function properly.- Parameters:
criticalValueAtEnter- the (opaque) value returned from the matchingwriterCriticalSectionEnter()call.
-
readerLock
public void readerLock()
Enter to a critical section containing a read operation (reentrant, mutually excludes againstreaderLockcalls by other threads).readerLockDOES NOT provide synchronization againstwriterCriticalSectionEnter()calls. UseflipPhase()to synchronize reads against writers.
-
readerUnlock
public void readerUnlock()
Exit from a critical section containing a read operation (relinquishes mutual exclusion against otherreaderLockcalls).
-
flipPhase
public void flipPhase(long yieldTimeNsec)
Flip a phase in theWriterReaderPhaserinstance,flipPhase()can only be called while holding thereaderLock.flipPhase()will return only after all writer critical sections (protected bywriterCriticalSectionEnterandwriterCriticalSectionEnter) that may have been in flight when theflipPhase()call were made had completed.No actual writer critical section activity is required for
flipPhase()to succeed.However,
flipPhase()is lock-free with respect to calls towriterCriticalSectionEnter()andwriterCriticalSectionExit(). It may spin-wait or for active writer critical section code to complete.- Parameters:
yieldTimeNsec- The amount of time (in nanoseconds) to sleep in each yield if yield loop is needed.
-
flipPhase
public void flipPhase()
Flip a phase in theWriterReaderPhaserinstance,flipPhase()can only be called while holding thereaderLock.flipPhase()will return only after all writer critical sections (protected bywriterCriticalSectionEnterandwriterCriticalSectionEnter) that may have been in flight when theflipPhase()call were made had completed.No actual writer critical section activity is required for
flipPhase()to succeed.However,
flipPhase()is lock-free with respect to calls towriterCriticalSectionEnter()andwriterCriticalSectionExit(). It may spin-wait or for active writer critical section code to complete.
-
-