C# Class HdrHistogram.Utilities.WriterReaderPhaser

WriterReaderPhaser instances provide 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.

While aWriterReaderPhaser can be useful in multiple scenarios, a specific and common use case is that of safely managing "double buffered" data stream access. This style of access allows writers to proceed without being blocked, while readers gain access to stable and unchanging buffer samples

NOTE: WriterReaderPhaser writers 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.
WriterReaderPhaser "writers" are wait free, "readers" block for other "readers", and "readers" are only blocked by "writers" whose critical was entered before the reader's FlipPhase() attempt.

When used to protect an actively recording data structure, the assumptions on how readers and writers act are:

  1. There are two sets of data structures("active" and "inactive")
  2. Writing is done to the perceived active version(as perceived by the writer), and only within critical sections delineated by WriterCriticalSectionEnter() and WriterCriticalSectionExit(long)).
  3. Only readers switch the perceived roles of the active and inactive data structures. They do so only while under ReaderLock(), and only before calling FlipPhase().
When the above assumptions are met, WriterReaderPhaser guarantees that the inactive data structures are not being modified by any writers while being read while under ReaderLock() protection after a FlipPhase() operation.

Mostra file Open project: HdrHistogram/HdrHistogram.NET

Public Methods

Method Description
FlipPhase ( ) : void

Flip a phase in the WriterReaderPhaser instance, FlipPhase() can only be called while holding the ReaderLock().

FlipPhase() will return only after all writer critical sections (protected by WriterCriticalSectionEnter() and WriterCriticalSectionExit(long) that may have been in flight when the FlipPhase(System.TimeSpan) 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 to WriterCriticalSectionEnter() and WriterCriticalSectionExit(long). It may spin-wait for for active writer critical section code to complete.

FlipPhase ( System.TimeSpan yieldPeriod ) : void

Flip a phase in the WriterReaderPhaser instance, FlipPhase(System.TimeSpan) can only be called while holding the ReaderLock().

FlipPhase(System.TimeSpan) will return only after all writer critical sections (protected by WriterCriticalSectionEnter() and WriterCriticalSectionExit(long) that may have been in flight when the FlipPhase(System.TimeSpan) call were made had completed.

No actual writer critical section activity is required for FlipPhase(System.TimeSpan) to succeed.

However, FlipPhase(System.TimeSpan) is lock-free with respect to calls to WriterCriticalSectionEnter() and WriterCriticalSectionExit(long). It may spin-wait for for active writer critical section code to complete.

ReaderLock ( ) : void

Enter to a critical section containing a read operation (mutually excludes against other ReaderLock() calls). ReaderLock DOES NOT provide synchronization against WriterCriticalSectionEnter calls. Use FlipPhase() to synchronize reads against writers.

ReaderUnlock ( ) : void

Exit from a critical section containing a read operation(relinquishes mutual exclusion against other ReaderLock() calls).

WriterCriticalSectionEnter ( ) : long

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 subsequent WriterCriticalSectionExit in order for CriticalSectionPhaser synchronization to function properly.

The IDisposable pattern could have been used but was not due to the high allocation count it would have incurred.

WriterCriticalSectionExit ( long criticalValueAtEnter ) : void

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 preceding WriterCriticalSectionEnter call, and must be provided with the matching WriterCriticalSectionEnter call's return value, in order for CriticalSectionPhaser synchronization to function properly.

Private Methods

Method Description
GetAndIncrement ( long &value ) : long
GetAndSet ( long &value, long newValue ) : long
LazySet ( long &value, long newValue ) : void

Method Details

FlipPhase() public method

Flip a phase in the WriterReaderPhaser instance, FlipPhase() can only be called while holding the ReaderLock().
FlipPhase() will return only after all writer critical sections (protected by WriterCriticalSectionEnter() and WriterCriticalSectionExit(long) that may have been in flight when the FlipPhase(System.TimeSpan) 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 to WriterCriticalSectionEnter() and WriterCriticalSectionExit(long). It may spin-wait for for active writer critical section code to complete.

public FlipPhase ( ) : void
return void

FlipPhase() public method

Flip a phase in the WriterReaderPhaser instance, FlipPhase(System.TimeSpan) can only be called while holding the ReaderLock().
FlipPhase(System.TimeSpan) will return only after all writer critical sections (protected by WriterCriticalSectionEnter() and WriterCriticalSectionExit(long) that may have been in flight when the FlipPhase(System.TimeSpan) call were made had completed.

No actual writer critical section activity is required for FlipPhase(System.TimeSpan) to succeed.

However, FlipPhase(System.TimeSpan) is lock-free with respect to calls to WriterCriticalSectionEnter() and WriterCriticalSectionExit(long). It may spin-wait for for active writer critical section code to complete.

public FlipPhase ( System.TimeSpan yieldPeriod ) : void
yieldPeriod System.TimeSpan The amount of time to sleep in each yield if yield loop is needed.
return void

ReaderLock() public method

Enter to a critical section containing a read operation (mutually excludes against other ReaderLock() calls). ReaderLock DOES NOT provide synchronization against WriterCriticalSectionEnter calls. Use FlipPhase() to synchronize reads against writers.
public ReaderLock ( ) : void
return void

ReaderUnlock() public method

Exit from a critical section containing a read operation(relinquishes mutual exclusion against other ReaderLock() calls).
public ReaderUnlock ( ) : void
return void

WriterCriticalSectionEnter() public method

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 subsequent WriterCriticalSectionExit in order for CriticalSectionPhaser synchronization to function properly.

The IDisposable pattern could have been used but was not due to the high allocation count it would have incurred.

public WriterCriticalSectionEnter ( ) : long
return long

WriterCriticalSectionExit() public method

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 preceding WriterCriticalSectionEnter call, and must be provided with the matching WriterCriticalSectionEnter call's return value, in order for CriticalSectionPhaser synchronization to function properly.

public WriterCriticalSectionExit ( long criticalValueAtEnter ) : void
criticalValueAtEnter long the opaque value (token) returned from the matching call.
return void