Skip to content

Commit 7257358

Browse files
authored
Merge pull request #91 from paulpach/lockless
Lockless doubles
2 parents 62b7a1a + 92c66b0 commit 7257358

File tree

2 files changed

+68
-60
lines changed

2 files changed

+68
-60
lines changed

MLAPI.Tests/NetworkingManagerComponents/Binary/BitStreamTest.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,21 @@ public void TestWriteDouble()
330330

331331
}
332332

333+
[Test]
334+
public void TestWriteDoublePacked()
335+
{
336+
double somenumber = Math.PI;
337+
BitStream outStream = new BitStream();
338+
339+
outStream.WriteDoublePacked(somenumber);
340+
byte[] buffer = outStream.GetBuffer();
341+
342+
BitStream inStream = new BitStream(buffer);
343+
344+
Assert.That(inStream.ReadDoublePacked(), Is.EqualTo(somenumber));
345+
346+
}
347+
333348
[Test]
334349
public void TestWriteMisaligned()
335350
{

MLAPI/NetworkingManagerComponents/Binary/BitStream.cs

Lines changed: 53 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
using System;
22
using System.IO;
3+
using System.Runtime.InteropServices;
4+
using System.Security;
35
using UnityEngine;
46
using static MLAPI.NetworkingManagerComponents.Binary.Arithmetic;
57

@@ -10,13 +12,27 @@ namespace MLAPI.NetworkingManagerComponents.Binary
1012
/// </summary>
1113
public sealed class BitStream : Stream
1214
{
15+
16+
[StructLayout(LayoutKind.Explicit)]
17+
internal struct UIntFloat
18+
{
19+
[FieldOffset(0)]
20+
public float floatValue;
21+
22+
[FieldOffset(0)]
23+
public uint intValue;
24+
25+
[FieldOffset(0)]
26+
public double doubleValue;
27+
28+
[FieldOffset(0)]
29+
public ulong longValue;
30+
}
31+
32+
1333
const int initialCapacity = 16;
1434
const float initialGrowthFactor = 2.0f;
1535
private byte[] target;
16-
private static readonly float[] holder_f = new float[1];
17-
private static readonly double[] holder_d = new double[1];
18-
private static readonly uint[] holder_i = new uint[1];
19-
private static readonly ulong[] holder_l = new ulong[1];
2036

2137
/// <summary>
2238
/// A stream that supports writing data smaller than a single byte. This stream also has a built-in compression algorithm that can (optionally) be used to write compressed data.
@@ -285,13 +301,10 @@ public void WriteBit(bool bit)
285301
/// <param name="value">Value to write</param>
286302
public void WriteSingle(float value)
287303
{
288-
lock (holder_f)
289-
lock (holder_i)
290-
{
291-
holder_f[0] = value;
292-
Buffer.BlockCopy(holder_f, 0, holder_i, 0, 4);
293-
WriteUInt32(holder_i[0]);
294-
}
304+
UIntFloat conversion = new UIntFloat();
305+
conversion.floatValue = value;
306+
uint binary = conversion.intValue;
307+
WriteUInt32(binary);
295308
}
296309

297310
/// <summary>
@@ -300,13 +313,11 @@ public void WriteSingle(float value)
300313
/// <param name="value">Value to write</param>
301314
public void WriteDouble(double value)
302315
{
303-
lock (holder_d)
304-
lock (holder_l)
305-
{
306-
holder_d[0] = value;
307-
Buffer.BlockCopy(holder_d, 0, holder_l, 0, 8);
308-
WriteUInt64(holder_l[0]);
309-
}
316+
UIntFloat conversion = new UIntFloat();
317+
conversion.doubleValue = value;
318+
ulong binary = conversion.longValue;
319+
WriteUInt64(binary);
320+
310321
}
311322

312323
/// <summary>
@@ -315,13 +326,10 @@ public void WriteDouble(double value)
315326
/// <param name="value">Value to write</param>
316327
public void WriteSinglePacked(float value)
317328
{
318-
lock (holder_f)
319-
lock (holder_i)
320-
{
321-
holder_f[0] = value;
322-
Buffer.BlockCopy(holder_f, 0, holder_i, 0, 4);
323-
WriteUInt32Packed(BinaryHelpers.SwapEndian(holder_i[0]));
324-
}
329+
UIntFloat conversion = new UIntFloat();
330+
conversion.floatValue = value;
331+
uint binary = conversion.intValue;
332+
WriteUInt32Packed(binary);
325333
}
326334

327335
/// <summary>
@@ -330,13 +338,11 @@ public void WriteSinglePacked(float value)
330338
/// <param name="value">Value to write</param>
331339
public void WriteDoublePacked(double value)
332340
{
333-
lock (holder_d)
334-
lock (holder_l)
335-
{
336-
holder_d[0] = value;
337-
Buffer.BlockCopy(holder_d, 0, holder_l, 0, 8);
338-
WriteUInt64Packed(BinaryHelpers.SwapEndian(holder_l[0]));
339-
}
341+
UIntFloat conversion = new UIntFloat();
342+
conversion.doubleValue = value;
343+
ulong binary = conversion.longValue;
344+
345+
WriteUInt64Packed(binary);
340346
}
341347

342348
/// <summary>
@@ -516,13 +522,10 @@ public void WriteRotation(Quaternion rotation, int bytesPerAngle)
516522
public float ReadSingle()
517523
{
518524
uint read = ReadUInt32();
519-
lock (holder_f)
520-
lock (holder_i)
521-
{
522-
holder_i[0] = read;
523-
Buffer.BlockCopy(holder_i, 0, holder_f, 0, 4);
524-
return holder_f[0];
525-
}
525+
526+
UIntFloat conversion = new UIntFloat();
527+
conversion.intValue = read;
528+
return conversion.floatValue;
526529
}
527530

528531

@@ -533,14 +536,12 @@ public float ReadSingle()
533536
public double ReadDouble()
534537
{
535538
ulong read = ReadUInt64();
536-
lock (holder_d)
537-
lock (holder_l)
538-
{
539-
holder_l[0] = read;
540-
Buffer.BlockCopy(holder_l, 0, holder_d, 0, 8);
541-
return holder_d[0];
542-
}
539+
540+
UIntFloat conversion = new UIntFloat();
541+
conversion.longValue = read;
542+
return conversion.doubleValue;
543543
}
544+
544545

545546
/// <summary>
546547
/// Read a single-precision floating point value from the stream from a varint
@@ -549,13 +550,9 @@ public double ReadDouble()
549550
public float ReadSinglePacked()
550551
{
551552
uint read = ReadUInt32Packed();
552-
lock (holder_f)
553-
lock (holder_i)
554-
{
555-
holder_i[0] = BinaryHelpers.SwapEndian(read);
556-
Buffer.BlockCopy(holder_i, 0, holder_f, 0, 4);
557-
return holder_f[0];
558-
}
553+
UIntFloat conversion = new UIntFloat();
554+
conversion.intValue = read;
555+
return conversion.floatValue;
559556
}
560557

561558
/// <summary>
@@ -565,13 +562,9 @@ public float ReadSinglePacked()
565562
public double ReadDoublePacked()
566563
{
567564
ulong read = ReadUInt64Packed();
568-
lock (holder_d)
569-
lock (holder_l)
570-
{
571-
holder_l[0] = BinaryHelpers.SwapEndian(read);
572-
Buffer.BlockCopy(holder_l, 0, holder_d, 0, 8);
573-
return holder_d[0];
574-
}
565+
UIntFloat conversion = new UIntFloat();
566+
conversion.longValue = read;
567+
return conversion.doubleValue;
575568
}
576569

577570
/// <summary>

0 commit comments

Comments
 (0)