using System; using System.Buffers; using System.Runtime.CompilerServices; /*https://github.com/sidristij/memory-pools*/ namespace MemoryPools.Memory { /// /// Encapsulates manual memory management mechanism. Holds /// IMemoryOwner instance goes to GC (link = null!) only when /// all owning entities called Dispose() method. This means, /// that only this mechanism should be used for covering /// managed instances. /// public sealed class CountdownMemoryOwner : IMemoryOwner { private int _length; private int _offset; private int _owners; private T[] _arr; private CountdownMemoryOwner _parent; private Memory _memory; public Memory Memory { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => _memory; private set => _memory = value; } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal CountdownMemoryOwner Init(CountdownMemoryOwner parent, int offset, int length, bool defaultOwner = true) { _owners = defaultOwner ? 1 : 0; _offset = offset; _length = length; _parent = parent; _parent.AddOwner(); Memory = _parent.Memory.Slice(_offset, _length); return this; } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal CountdownMemoryOwner Init(T[] array, int length) { _owners = 1; _offset = 0; _length = length; _parent = default!; _arr = array; Memory = _arr.AsMemory(0, _length); return this; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void AddOwner() => _owners++; [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Dispose() { _owners--; if (_owners > 0) { return; } if (_parent != default) { _parent.Dispose(); _parent = null!; } else { ArrayPool.Shared.Return(_arr); } Pool>.Return(this); } } }