DotNext by .NET Foundation and Contributors

<PackageReference Include="DotNext" Version="5.16.0" />

.NET API 532,936 bytes

 SpanOwner<T>

public struct SpanOwner<T>
Represents the memory obtained from the pool or allocated on the stack or heap.
using DotNext.Runtime; using System; using System.Buffers; using System.ComponentModel; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; namespace DotNext.Buffers { [StructLayout(LayoutKind.Auto)] [NullableContext(1)] [Nullable(0)] [CompilerFeatureRequired("RefStructs")] public ref struct SpanOwner<[Nullable(2)] T> { private readonly object owner; private readonly Span<T> memory; [EditorBrowsable(EditorBrowsableState.Never)] [CLSCompliant(false)] public static int StackallocThreshold { get; } = 1 + LibrarySettings.StackallocThreshold / Unsafe.SizeOf<T>(); private static bool UseNativeAllocation { get { if (!LibrarySettings.DisableNativeAllocation && !RuntimeHelpers.IsReferenceOrContainsReferences<T>()) return Intrinsics.AlignOf<T>() <= UIntPtr.Size; return false; } } [Nullable(new byte[] { 0, 1 })] public Span<T> Span { [IsReadOnly] [return: Nullable(new byte[] { 0, 1 })] get { return memory; } } public bool IsEmpty { [IsReadOnly] get { return memory.IsEmpty; } } public int Length { [IsReadOnly] get { return memory.Length; } } public ref T this[int index] { [IsReadOnly] get { return ref memory[index]; } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public SpanOwner([Nullable(new byte[] { 0, 1 })] Span<T> span) { owner = null; memory = span; } public SpanOwner([Nullable(new byte[] { 0, 1 })] Span<T> span, int length) { this = new SpanOwner<T>(span.Slice(0, length)); } public SpanOwner(MemoryPool<T> pool, int minBufferSize, bool exactSize = true) { ArgumentNullException.ThrowIfNull((object)pool, "pool"); ArgumentOutOfRangeException.ThrowIfNegativeOrZero<int>(minBufferSize, "minBufferSize"); IMemoryOwner<T> memoryOwner = pool.Rent(minBufferSize); memory = memoryOwner.Memory.Span; if (exactSize) memory = memory.Slice(0, minBufferSize); owner = memoryOwner; } public SpanOwner(MemoryPool<T> pool) { ArgumentNullException.ThrowIfNull((object)pool, "pool"); IMemoryOwner<T> memoryOwner = pool.Rent(-1); memory = memoryOwner.Memory.Span; owner = memoryOwner; } public unsafe SpanOwner(int minBufferSize, bool exactSize = true) { if (UseNativeAllocation) { ArgumentOutOfRangeException.ThrowIfNegativeOrZero<int>(minBufferSize, "minBufferSize"); void* pointer = NativeMemory.Alloc((UIntPtr)(uint)minBufferSize, (UIntPtr)(uint)Unsafe.SizeOf<T>()); memory = new Span<T>(pointer, minBufferSize); owner = Sentinel.Instance; } else { T[] array = ArrayPool<T>.Shared.Rent(minBufferSize); memory = (exactSize ? new Span<T>(array, 0, minBufferSize) : new Span<T>(array)); owner = array; } } public static implicit operator SpanOwner<T>([Nullable(new byte[] { 0, 1 })] Span<T> span) { return new SpanOwner<T>(span); } [MethodImpl(MethodImplOptions.AggressiveInlining)] [IsReadOnly] [EditorBrowsable(EditorBrowsableState.Never)] public ref T GetPinnableReference() { return ref memory.GetPinnableReference(); } [IsReadOnly] public override string ToString() { return memory.ToString(); } public unsafe void Dispose() { T[] array = owner as T[]; if (array != null) ArrayPool<T>.Shared.Return(array, RuntimeHelpers.IsReferenceOrContainsReferences<T>()); else if (owner == Sentinel.Instance) { NativeMemory.Free(Unsafe.AsPointer<T>(ref MemoryMarshal.GetReference<T>(memory))); } else { Unsafe.As<IDisposable>(owner)?.Dispose(); } this = default(SpanOwner<T>); } } }