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
clearArrayboolWhether each buffer is zeroed as it returns to the array pool.
defaultChunkBytesintThe size, in bytes, of the first chunk rented.
maxChunkBytesintThe ceiling, in bytes, the chunk size ramps up to. A value at or below
defaultChunkBytesdisables 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
defaultChunkBytesis less than one.
ArrayPoolBufferWriter(int, int)
Initializes a new instance of the ArrayPoolBufferWriter<T> class.
public ArrayPoolBufferWriter(int defaultChunkBytes, int maxChunkBytes)
Parameters
Fields
DefaultChunkBytes
The default size, in bytes, of the first chunk a writer rents.
public const int DefaultChunkBytes = 256
Field Value
MaxChunkBytes
The default ceiling, in bytes, on how large a single chunk may grow.
public const int MaxChunkBytes = 65536
Field Value
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
countint
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
sizeHintint
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
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
sizeHintint
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.