Skip to content

Instantly share code, notes, and snippets.

@svick
Created October 23, 2017 23:50
Show Gist options
  • Save svick/1ddc3e59d1d9bc12c809064973b1d523 to your computer and use it in GitHub Desktop.
Save svick/1ddc3e59d1d9bc12c809064973b1d523 to your computer and use it in GitHub Desktop.
// based on https://github.com/dotnet/corefx/blob/389d7ee/src/System.Memory/tests/Memory/CustomMemoryForTest.cs
unsafe class HGlobalMemory : OwnedMemory<byte>
{
private bool _disposed;
private int _referenceCount;
private byte* _buffer;
private int _length;
public HGlobalMemory(int length)
{
_buffer = (byte*)Marshal.AllocHGlobal(length);
_length = length;
}
public override int Length => _length;
public override bool IsDisposed => _disposed;
protected override bool IsRetained => _referenceCount > 0;
public override Span<byte> AsSpan()
{
if (IsDisposed)
throw new ObjectDisposedException(nameof(HGlobalMemory));
return new Span<byte>(_buffer, _length);
}
public override MemoryHandle Pin()
{
Retain();
return new MemoryHandle(this, _buffer);
}
protected override bool TryGetArray(out ArraySegment<byte> arraySegment)
{
if (IsDisposed)
throw new ObjectDisposedException(nameof(HGlobalMemory));
arraySegment = default;
return false;
}
protected override void Dispose(bool disposing)
{
if (_disposed)
return;
Marshal.FreeHGlobal((IntPtr)_buffer);
_buffer = null;
if (disposing)
GC.SuppressFinalize(this);
_disposed = true;
}
~HGlobalMemory() => Dispose(false);
public override void Retain()
{
if (IsDisposed)
throw new ObjectDisposedException(nameof(HGlobalMemory));
Interlocked.Increment(ref _referenceCount);
}
public override bool Release()
{
int newRefCount = Interlocked.Decrement(ref _referenceCount);
if (newRefCount < 0)
throw new InvalidOperationException();
return newRefCount != 0;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment