This repository has been archived by the owner on Jun 11, 2021. It is now read-only.
forked from dotnet/dotNext
-
Notifications
You must be signed in to change notification settings - Fork 1
/
UnmanagedMemory.cs
85 lines (71 loc) · 2.57 KB
/
UnmanagedMemory.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
using System;
using System.Buffers;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace DotNext.Buffers
{
using Runtime;
internal class UnmanagedMemory<T> : MemoryManager<T>
where T : unmanaged
{
private readonly bool owner;
private IntPtr address;
internal UnmanagedMemory(nint address, int length)
{
this.address = address;
Length = length;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private protected static unsafe long SizeOf(int length) => Math.BigMul(length, sizeof(T));
private protected unsafe UnmanagedMemory(int length, bool zeroMem)
{
var size = SizeOf(length);
address = Marshal.AllocHGlobal(new IntPtr(size));
GC.AddMemoryPressure(size);
Length = length;
if (zeroMem)
Intrinsics.ClearBits(address.ToPointer(), size);
owner = true;
}
private protected IntPtr Address
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
var result = address;
return result == default ? throw new ObjectDisposedException(GetType().Name) : result;
}
}
public long Size => SizeOf(Length);
public int Length { get; private set; }
internal void Reallocate(int length)
{
if (length <= 0)
throw new ArgumentOutOfRangeException(nameof(length));
if (address == default)
throw new ObjectDisposedException(GetType().Name);
long oldSize = Size, newSize = SizeOf(Length = length);
address = Marshal.ReAllocHGlobal(address, new IntPtr(newSize));
var diff = newSize - oldSize;
if (diff > 0L)
GC.AddMemoryPressure(diff);
else if (diff < 0L)
GC.RemoveMemoryPressure(Math.Abs(diff));
}
public sealed override unsafe Span<T> GetSpan() => new Span<T>(Address.ToPointer(), Length);
public sealed override unsafe MemoryHandle Pin(int elementIndex = 0)
=> new MemoryHandle((T*)Address.ToPointer() + elementIndex);
public sealed override void Unpin()
{
}
protected override void Dispose(bool disposing)
{
if (address != default && owner)
{
Marshal.FreeHGlobal(address);
GC.RemoveMemoryPressure(Size);
}
address = default;
}
}
}