Table of Contents

Class RingBuffer<T>

Namespace
MarymoorStudios.Core.Promises
Assembly
MarymoorStudios.Core.Promises.dll

A fixed-sized, shared-memory, Transport<T>.

public sealed class RingBuffer<T> : Transport<T>, IAsyncDisposable

Type Parameters

T

The item type.

Inheritance
RingBuffer<T>
Implements
Inherited Members

Constructors

RingBuffer(ushort, ushort)

Constructs a new RingBuffer<T>

public RingBuffer(ushort capacity, ushort threshold = 1)

Parameters

capacity ushort

The size of the buffer allocated (in number of items).

threshold ushort

The number of items of empty space available before the producer is signaled.

Remarks

REQUIRES: capacity > 2

REQUIRES: 1 <= threshold < capacity -1

Capacity is equal to the size of the memory allocation (in number of items) but one item is consumed as a sentinel for "full", so the buffer can actually hold one less.

Threshold is used to decrease ping-ponging by delaying waking the producer until there are more items in the buffer. There is a tradeoff between added latency and buffering costs on the writer side versus signalling costs. The default value is 1 causing the producer to be signalled whenever there is at least one slot available.

Properties

ConsumerEvent

Event to efficiently signal the consumer when items are available to read.

public override sealed WaitHandle ConsumerEvent { get; }

Property Value

WaitHandle

Remarks

This event only signals on the transition between an empty queue and having at least one item, so the caller should read the queue to completion before waiting on this event.

ProducerEvent

Event to efficiently signal the producer when slots are available to write.

public override sealed WaitHandle ProducerEvent { get; }

Property Value

WaitHandle

Remarks

This event only signals on the transition between a full queue and having at least threshold items, so the caller should write to the queue until full before waiting on this event.

Methods

Close(TransportFlags)

Marks the buffer as closed atomically.

public override sealed bool Close(TransportFlags flags = TransportFlags.Closed)

Parameters

flags TransportFlags

Indicates which side(s) to close.

Returns

bool

True if the both sides have closed, false if only one side has closed as of this call.

Remarks

No more items can be inserted after this call returns.

Either side (producer or consumer) can close the buffer.

Typically, the consumer will continue to read items until TryDequeue(out T) indicates the closure has been seen. This ensures that all buffered items have been removed, regardless of which side closed first.

Both sides should close the buffer before the last side to close can then safely dispose.

DisposeAsync(bool)

Standard dispose pattern for subclasses.

protected override sealed ValueTask DisposeAsync(bool disposing)

Parameters

disposing bool

True if both native and managed resources are being disposed. False if only native resources (i.e. in finalizer). When native only then MUST be prompt.

Returns

ValueTask

TryDequeue(out T)

Attempt to remove an item from the front of the buffer.

public override sealed bool TryDequeue(out T item)

Parameters

item T

If successful, the item removed from the buffer, default otherwise.

Returns

bool

True if an item was successfully remove, false if the buffer is empty.

Remarks

If item is successfully removed the caller takes ownership of it and is responsible for releasing its resources. If the attempt to dequeue fails then item is default.

Exceptions

AbortedException

If the buffer has been closed AND all buffered items have been read.

TryEnqueue(ref T)

Attempt to insert an item at the end of the buffer.

public override sealed bool TryEnqueue(ref T item)

Parameters

item T

The item to be inserted.

Returns

bool

True if the item was inserted, false if the buffer is full.

Remarks

On a successful insert the buffer takes ownership of item and its value is set to default. If item cannot be inserted (either because 'full' or 'closed') then false is returned and item is unmodified (still owned by the caller); the caller is then responsible for releasing any resources.

Exceptions

AbortedException

If the buffer has already been closed.