Skip to content

Commit d9ea3e0

Browse files
author
Olivier Deheurles
committed
Merge pull request aeron-io#106 from qed-/directbuffer
Recycleable DirectBuffer, Resolves aeron-io#101
2 parents 9434c64 + 29f85b8 commit d9ea3e0

File tree

2 files changed

+63
-8
lines changed

2 files changed

+63
-8
lines changed

main/csharp/DirectBuffer.cs

Lines changed: 42 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,45 @@ namespace Adaptive.SimpleBinaryEncoding
88
/// </summary>
99
public sealed unsafe class DirectBuffer : IDisposable
1010
{
11-
private readonly byte* _pBuffer;
11+
private byte* _pBuffer;
1212
private bool _disposed;
1313
private GCHandle _pinnedGCHandle;
14-
private readonly bool _needToFreeGCHandle;
15-
private readonly int _capacity;
14+
private bool _needToFreeGCHandle;
15+
private int _capacity;
1616

1717
/// <summary>
1818
/// Constructs a <see cref="DirectBuffer"/>
1919
/// </summary>
2020
/// <param name="byteArray">The byte array that will act as the backing buffer.</param>
2121
public DirectBuffer(byte[] byteArray)
22+
{
23+
Reset(byteArray);
24+
}
25+
26+
/// <summary>
27+
/// Constructs a <see cref="DirectBuffer"/> from an unmanaged byte buffer owned by external code
28+
/// </summary>
29+
/// <param name="pBuffer">Unmanaged byte buffer</param>
30+
/// <param name="bufferLength">Length of the buffer</param>
31+
public DirectBuffer(byte* pBuffer, int bufferLength)
32+
{
33+
Reset(pBuffer, bufferLength);
34+
}
35+
36+
public DirectBuffer()
37+
{
38+
}
39+
40+
/// <summary>
41+
/// Recycles an existing <see cref="DirectBuffer"/>
42+
/// </summary>
43+
/// <param name="byteArray">The byte array that will act as the backing buffer.</param>
44+
public void Reset(byte[] byteArray)
2245
{
2346
if (byteArray == null) throw new ArgumentNullException("byteArray");
2447

48+
FreeGCHandle();
49+
2550
// pin the buffer so it does not get moved around by GC, this is required since we use pointers
2651
_pinnedGCHandle = GCHandle.Alloc(byteArray, GCHandleType.Pinned);
2752
_needToFreeGCHandle = true;
@@ -31,15 +56,17 @@ public DirectBuffer(byte[] byteArray)
3156
}
3257

3358
/// <summary>
34-
/// Constructs a <see cref="DirectBuffer"/> from an unmanaged byte buffer owned by external code
59+
/// Recycles an existing <see cref="DirectBuffer"/> from an unmanaged byte buffer owned by external code
3560
/// </summary>
3661
/// <param name="pBuffer">Unmanaged byte buffer</param>
3762
/// <param name="bufferLength">Length of the buffer</param>
38-
public DirectBuffer(byte* pBuffer, int bufferLength)
63+
public void Reset(byte* pBuffer, int bufferLength)
3964
{
4065
if (pBuffer == null) throw new ArgumentNullException("pBuffer");
4166
if (bufferLength < 0) throw new ArgumentException("Buffer size must be > 0", "bufferLength");
4267

68+
FreeGCHandle();
69+
4370
_pBuffer = pBuffer;
4471
_capacity = bufferLength;
4572
_needToFreeGCHandle = false;
@@ -539,10 +566,18 @@ private void Dispose(bool disposing)
539566
if (_disposed)
540567
return;
541568

542-
if (_needToFreeGCHandle)
543-
_pinnedGCHandle.Free();
569+
FreeGCHandle();
544570

545571
_disposed = true;
546572
}
573+
574+
private void FreeGCHandle()
575+
{
576+
if (_needToFreeGCHandle)
577+
{
578+
_pinnedGCHandle.Free();
579+
_needToFreeGCHandle = false;
580+
}
581+
}
547582
}
548583
}

test/csharp/DirectBufferTests.cs

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,27 @@ public void ConstructFromNativeBuffer()
5050
Assert.AreEqual(value, *(long*) (unmanagedBuffer + index));
5151
}
5252
}
53-
53+
54+
[Test]
55+
public void Recycle()
56+
{
57+
var directBuffer = new DirectBuffer();
58+
var firstBuffer = new Byte[16];
59+
directBuffer.Reset(firstBuffer);
60+
61+
directBuffer.Int64PutLittleEndian(0, 1);
62+
Assert.AreEqual(1, BitConverter.ToInt64(firstBuffer, 0));
63+
64+
var secondBuffer = new byte[16];
65+
var secondBufferHandle = GCHandle.Alloc(secondBuffer, GCHandleType.Pinned);
66+
var secondUnmanagedBuffer = (byte*)secondBufferHandle.AddrOfPinnedObject().ToPointer();
67+
directBuffer.Reset(secondUnmanagedBuffer, 16);
68+
directBuffer.Int64PutLittleEndian(0, 2);
69+
Assert.AreEqual(2, BitConverter.ToInt64(secondBuffer, 0));
70+
71+
directBuffer.Dispose();
72+
}
73+
5474
#region Byte
5575

5676
[TestCase(5, 0)]

0 commit comments

Comments
 (0)