-
Notifications
You must be signed in to change notification settings - Fork 1
/
MemoryPool.cs
210 lines (181 loc) · 5.59 KB
/
MemoryPool.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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.IO;
using System.Linq;
using System.Diagnostics;
namespace VVVV.DX11
{
abstract class MemoryPool<T> : IDisposable
{
private readonly Dictionary<int, Stack<T>> FMemoryPools = new Dictionary<int, Stack<T>>();
private long FHandedOutBytes;
protected abstract T Allocate(int length);
protected abstract void Free(T mem);
public T GetMemory(int length)
{
lock (this)
{
Stack<T> memoryPool = null;
if (!FMemoryPools.TryGetValue(length, out memoryPool))
{
memoryPool = new Stack<T>(1);
FMemoryPools[length] = memoryPool;
}
FHandedOutBytes += length;
if (memoryPool.Count > 0)
return memoryPool.Pop();
else
return Allocate(length);
}
}
public void PutMemory(T mem, int length)
{
lock (this)
{
var memoryPool = FMemoryPools[length];
FHandedOutBytes -= length;
memoryPool.Push(mem);
}
}
public void ReleaseUnused(int capacity)
{
lock (this)
{
foreach (var memoryPool in FMemoryPools.Values)
{
while (memoryPool.Count > capacity)
{
var mem = memoryPool.Pop();
Free(mem);
}
}
}
}
public void Dispose()
{
lock (this)
{
ReleaseUnused(0);
FMemoryPools.Clear();
}
}
public override string ToString()
{
return string.Format("Unused: {0}, Used: {1}", FMemoryPools.Keys.Select(length => FMemoryPools[length].Count * length).Sum(), FHandedOutBytes);
}
}
class MemoryPool : IDisposable
{
public MemoryPool()
{
ManagedPool = new ManagedMemoryPool();
ManagedStreamPool = new ManagedStreamPool(ManagedPool);
UnmanagedPool = new UnmanagedMemoryPool();
StreamPool = new UnmanagedStreamPool(UnmanagedPool);
}
public ManagedMemoryPool ManagedPool
{
get;
private set;
}
public ManagedStreamPool ManagedStreamPool
{
get;
private set;
}
public UnmanagedMemoryPool UnmanagedPool
{
get;
private set;
}
public UnmanagedStreamPool StreamPool
{
get;
private set;
}
public void ReleaseUnused(int capacity)
{
ManagedPool.ReleaseUnused(capacity);
UnmanagedPool.ReleaseUnused(capacity);
}
public void Dispose()
{
ManagedPool.Dispose();
UnmanagedPool.Dispose();
}
}
class ManagedMemoryPool : MemoryPool<byte[]>
{
protected override byte[] Allocate(int length)
{
return new byte[length];
}
protected override void Free(byte[] mem)
{
Debug.WriteLine("ManagedMemoryPool: released {0} bytes.", mem.Length);
}
public void PutMemory(byte[] array)
{
base.PutMemory(array, array.Length);
}
}
class UnmanagedMemoryPool : MemoryPool<IntPtr>
{
protected override IntPtr Allocate(int length)
{
return Marshal.AllocHGlobal(length);
}
protected override void Free(IntPtr mem)
{
Marshal.FreeHGlobal(mem);
//Debug.WriteLine("UnmanagedMemoryPool: released {0} bytes.", mem.Size);
}
public void PutMemory(IntPtr dp, int length)
{
base.PutMemory(dp, length);
}
}
class UnmanagedStreamPool
{
private readonly UnmanagedMemoryPool FUnmanagedMemoryPool;
public UnmanagedStreamPool(UnmanagedMemoryPool unmanagedMemoryPool)
{
FUnmanagedMemoryPool = unmanagedMemoryPool;
}
public unsafe Stream GetStream(int length)
{
var capacity = VVVV.Utils.Streams.StreamUtils.NextHigher(length);
var memory = FUnmanagedMemoryPool.GetMemory(capacity);
var stream = new SlimDX.DataStream(memory, length, true, true);
return stream;
}
public unsafe void PutStream(Stream stream)
{
var unmanagedStream = stream as SlimDX.DataStream;
var memory = unmanagedStream.DataPointer;
FUnmanagedMemoryPool.PutMemory(memory, (int)unmanagedStream.Length);
}
}
class ManagedStreamPool
{
private readonly ManagedMemoryPool FMemoryPool;
public ManagedStreamPool(ManagedMemoryPool memoryPool)
{
FMemoryPool = memoryPool;
}
public unsafe Stream GetStream(int length)
{
var capacity = VVVV.Utils.Streams.StreamUtils.NextHigher(length);
var memory = FMemoryPool.GetMemory(capacity);
var stream = new MemoryStream(memory, 0, length, true, true);
return stream;
}
public unsafe void PutStream(Stream stream)
{
var memoryStream = stream as MemoryStream;
FMemoryPool.PutMemory(memoryStream.GetBuffer());
memoryStream.Dispose();
}
}
}