Table of Contents

Class ArrayPoolBufferWriter<T>

Namespace
CryptoHives.Foundation.Memory.Buffers
Assembly
CryptoHives.Foundation.Memory.dll

Helper to build a ReadOnlySequence<T> from a set of buffers. Implements IBufferWriter<T> interface.

public sealed class ArrayPoolBufferWriter<T> : IBufferWriter<T>, IDisposable, IResettable

Type Parameters

T
Inheritance
ArrayPoolBufferWriter<T>
Implements
Inherited Members

Remarks

Instances can be pooled. Rent one with RentBufferWriter<T>() and dispose it as usual — a rented writer returns itself to its pool instead of being destroyed, and TryReset() puts it back into its just-constructed state on the way.

Using a rented writer after disposing it is undefined. Unlike an ordinary IDisposable, a returned instance does not throw ObjectDisposedException; it silently becomes whatever the next renter is doing. This is the same contract as ArrayPool<T> itself.

Constructors

ArrayPoolBufferWriter()

Initializes a new instance of the ArrayPoolBufferWriter<T> class.

public ArrayPoolBufferWriter()

ArrayPoolBufferWriter(bool, int, int)

Initializes a new instance of the ArrayPoolBufferWriter<T> class.

public ArrayPoolBufferWriter(bool clearArray, int defaultChunkBytes, int maxChunkBytes)

Parameters

clearArray bool

Whether each buffer is zeroed as it returns to the array pool.

defaultChunkBytes int

The size, in bytes, of the first chunk rented.

maxChunkBytes int

The ceiling, in bytes, the chunk size ramps up to. A value at or below defaultChunkBytes disables the ramp, pinning every chunk to that size.

Remarks

Both budgets are bytes, not elements, so they mean the same thing whatever T is: the writer divides by the size of one element to decide how many fit. That is what keeps a chunk off the large object heap for a wide element type — see MaxChunkBytes. For byte the two units coincide.

Exceptions

ArgumentOutOfRangeException

defaultChunkBytes is less than one.

ArrayPoolBufferWriter(int, int)

Initializes a new instance of the ArrayPoolBufferWriter<T> class.

public ArrayPoolBufferWriter(int defaultChunkBytes, int maxChunkBytes)

Parameters

defaultChunkBytes int
maxChunkBytes int

Fields

DefaultChunkBytes

The default size, in bytes, of the first chunk a writer rents.

public const int DefaultChunkBytes = 256

Field Value

int

MaxChunkBytes

The default ceiling, in bytes, on how large a single chunk may grow.

public const int MaxChunkBytes = 65536

Field Value

int

Remarks

64 KiB is not arbitrary. An object reaches the large object heap at 85,000 bytes, and ArrayPool<T> rounds a request up to a bucket of 16 × 2ⁿ elements — the bucket above 65,536 bytes is 131,072, with nothing in between. So 64 KiB is the largest budget whose rented array is guaranteed to stay off the LOH.

Methods

Advance(int)

Notifies IBufferWriter<T> that count amount of data was written to Span<T>/Memory<T>

public void Advance(int count)

Parameters

count int

Dispose()

Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.

public void Dispose()

Remarks

For a writer rented from a pool this returns the instance to that pool rather than destroying it, so it can be reused. See the remarks on ArrayPoolBufferWriter<T> for what that means for a reference held past disposal.

GetMemory(int)

Requests the Memory<T> that is at least sizeHint in size if possible, otherwise returns maximum available memory. If sizeHint is equal to

0

, currently available memory would get returned.

public Memory<T> GetMemory(int sizeHint = 0)

Parameters

sizeHint int

Returns

Memory<T>

GetReadOnlySequence()

Get a ReadOnlySequence that represents the written data. The sequence is only valid until the next write operation or until the writer is disposed.

public ReadOnlySequence<T> GetReadOnlySequence()

Returns

ReadOnlySequence<T>

Remarks

The sequence borrows the writer's buffers; it does not own them. Use LeaseSequence() when the payload has to leave the scope that built it.

GetSpan(int)

Requests the Span<T> that is at least sizeHint in size if possible, otherwise returns maximum available memory. If sizeHint is equal to

0

, currently available memory would get returned.

public Span<T> GetSpan(int sizeHint = 0)

Parameters

sizeHint int

Returns

Span<T>

LeaseSequence()

Pairs the written data with this writer as a single disposable value, so the payload can leave the scope that produced it.

public SequenceLease<T> LeaseSequence()

Returns

SequenceLease<T>

A SequenceLease<T> over the written data. Disposing it disposes this writer, which returns it to its pool if it was rented, and its buffers to the array pool.

Remarks

This allocates nothing — the lease is a struct, and the sequence is the one this writer already holds. It is the cheapest way to hand a payload to a caller:

static SequenceLease<byte> BuildPayload()
{
    var writer = ObjectPools.RentBufferWriter<byte>();   // deliberately not `using`
    Serialize(writer);
    return writer.LeaseSequence();
}

using SequenceLease<byte> payload = BuildPayload();
Send(payload.Sequence);

The writer stays alive for the life of the lease, so a rented one stays out of its pool for that long. Do not write to the writer after leasing: that invalidates the leased sequence exactly as it would one from GetReadOnlySequence().

Exceptions

ObjectDisposedException

The writer has been disposed.

TryReset()

Resets the writer to its just-constructed state so it can be reused.

public bool TryReset()

Returns

bool

true if the writer was reset and may be returned to a pool; false if it has been disposed and must be discarded.

Remarks

Implements IResettable from Microsoft.Extensions.ObjectPool. Every rented segment goes back to ArrayPool<T> — none is retained for the next use, because a pool that is already full drops the instance rather than keeping it, and a retained segment would then leak out of the pool. Idempotent.