MemoryOwner<T>
public struct MemoryOwner<T> : IMemoryOwner<T>, IDisposable, ISupplier<Memory<T>>, IFunctional<Func<Memory<T>>>, ISupplier<ReadOnlyMemory<T>>, IFunctional<Func<ReadOnlyMemory<T>>>
Represents unified representation of the memory rented using various
types of memory pools.
using DotNext.Runtime.CompilerServices;
using System;
using System.Buffers;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace DotNext.Buffers
{
[StructLayout(LayoutKind.Auto)]
[NullableContext(1)]
[Nullable(0)]
public struct MemoryOwner<[Nullable(2)] T> : IMemoryOwner<T>, IDisposable, ISupplier<Memory<T>>, IFunctional<Func<Memory<T>>>, ISupplier<ReadOnlyMemory<T>>, IFunctional<Func<ReadOnlyMemory<T>>>
{
private readonly object owner;
private readonly T[] array;
private int length;
public int Length {
[IsReadOnly]
get {
return length;
}
}
private int RawLength {
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[IsReadOnly]
get {
T[] obj = array;
if (obj == null) {
IMemoryOwner<T> memoryOwner = Unsafe.As<IMemoryOwner<T>>(owner);
if (memoryOwner == null)
return 0;
return memoryOwner.Memory.Length;
}
return obj.Length;
}
}
public bool IsEmpty {
[IsReadOnly]
get {
return length == 0;
}
}
[Nullable(new byte[] {
0,
1
})]
public Memory<T> Memory {
[IsReadOnly]
[return: Nullable(new byte[] {
0,
1
})]
get {
T[] obj = array;
if (obj == null) {
IMemoryOwner<T> memoryOwner = Unsafe.As<IMemoryOwner<T>>(owner);
if (memoryOwner == null)
return Memory<T>.Empty;
return memoryOwner.Memory.Slice(0, length);
}
return MemoryExtensions.AsMemory<T>(obj, 0, length);
}
}
[Nullable(new byte[] {
0,
1
})]
public Span<T> Span {
[IsReadOnly]
[return: Nullable(new byte[] {
0,
1
})]
get {
return MemoryMarshal.CreateSpan<T>(ref First, length);
}
}
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
internal ref T First {
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[IsReadOnly]
get {
if (array == null) {
if (owner == null)
return ref Unsafe.NullRef<T>();
return ref MemoryMarshal.GetReference<T>(Unsafe.As<IMemoryOwner<T>>(owner).Memory.Span);
}
return ref MemoryMarshal.GetArrayDataReference<T>(array);
}
}
public ref T this[int index] {
[IsReadOnly]
get {
ArgumentOutOfRangeException.ThrowIfGreaterThanOrEqual<uint>((uint)index, (uint)length, "index");
return ref Unsafe.Add<T>(ref First, index);
}
}
private MemoryOwner(IMemoryOwner<T> owner, int? length)
{
this.owner = (((this.length = (length ?? owner.Memory.Length)) > 0) ? owner : null);
array = null;
}
internal MemoryOwner(ArrayPool<T> pool, T[] array, int length)
{
this.array = array;
owner = pool;
this.length = length;
}
internal MemoryOwner(ArrayPool<T> pool, int length, bool exactSize)
{
if (length == 0)
this = default(MemoryOwner<T>);
else {
array = pool.Rent(length);
owner = pool;
this.length = (exactSize ? length : array.Length);
}
}
public MemoryOwner(ArrayPool<T> pool, int length)
{
this = new MemoryOwner<T>(pool, length, true);
}
public MemoryOwner(MemoryPool<T> pool, int length = -1)
{
if (length == 0)
this = default(MemoryOwner<T>);
else {
array = null;
IMemoryOwner<T> memoryOwner = pool.Rent(length);
if ((this.length = ((length < 0) ? memoryOwner.Memory.Length : length)) > 0)
owner = memoryOwner;
else {
memoryOwner.Dispose();
owner = null;
}
}
}
public MemoryOwner(Func<int, IMemoryOwner<T>> provider, int length)
{
if (length < 0)
throw new ArgumentOutOfRangeException("length");
if (length == 0)
this = default(MemoryOwner<T>);
else {
array = null;
IMemoryOwner<T> memoryOwner = provider(length);
if ((this.length = Math.Min(memoryOwner.Memory.Length, length)) > 0)
owner = memoryOwner;
else {
memoryOwner.Dispose();
owner = null;
}
}
}
public MemoryOwner(Func<IMemoryOwner<T>> provider)
{
array = null;
IMemoryOwner<T> memoryOwner = provider();
if ((length = memoryOwner.Memory.Length) > 0)
owner = memoryOwner;
else {
memoryOwner.Dispose();
owner = null;
}
}
public MemoryOwner(T[] array, int length)
{
ArgumentOutOfRangeException.ThrowIfGreaterThan<uint>((uint)length, (uint)array.Length, "length");
this.array = ((length > 0) ? array : null);
this.length = length;
owner = null;
}
public MemoryOwner(T[] array)
{
this = new MemoryOwner<T>(array, array.Length);
}
internal void Expand()
{
length = RawLength;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal void Truncate(int newLength)
{
length = Math.Min(length, newLength);
}
public bool TryResize(int newLength)
{
if (newLength < 0)
throw new ArgumentOutOfRangeException("newLength");
if (newLength == 0)
Dispose();
else {
if (newLength > RawLength)
return false;
length = newLength;
}
return true;
}
[IsReadOnly]
[Conditional("DEBUG")]
private void AssertValid()
{
}
[IsReadOnly]
Memory<T> ISupplier<Memory<T>>.Invoke()
{
return Memory;
}
[IsReadOnly]
ReadOnlyMemory<T> ISupplier<ReadOnlyMemory<T>>.Invoke()
{
return Memory;
}
[IsReadOnly]
internal void Clear(bool clearBuffer)
{
if (array == null)
Unsafe.As<IDisposable>(owner)?.Dispose();
else if (owner != null) {
Unsafe.As<ArrayPool<T>>(owner).Return(array, clearBuffer);
} else if (clearBuffer) {
Array.Clear((Array)array);
}
}
public void Dispose()
{
Clear(RuntimeHelpers.IsReferenceOrContainsReferences<T>());
this = default(MemoryOwner<T>);
}
[IsReadOnly]
public override string ToString()
{
return Span.ToString();
}
}
}