|
6 | 6 |
|
7 | 7 | namespace MLAPI.NetworkingManagerComponents.Binary
|
8 | 8 | {
|
9 |
| - public sealed class BitWiter : IDisposable |
| 9 | + public sealed class BitWriter : IDisposable |
10 | 10 | {
|
11 |
| - // Collects reusable |
12 |
| - private static readonly List<WeakReference> expired = new List<WeakReference>(); |
| 11 | + private static readonly Queue<List<object>> listPool = new Queue<List<object>>(); |
13 | 12 |
|
14 | 13 | private static readonly float[] holder_f = new float[1];
|
15 | 14 | private static readonly double[] holder_d = new double[1];
|
@@ -38,43 +37,45 @@ private static readonly FieldInfo
|
38 | 37 | dec_hi,
|
39 | 38 | dec_flags;
|
40 | 39 |
|
41 |
| - static BitWiter() |
| 40 | + static BitWriter() |
42 | 41 | {
|
43 | 42 | dec_lo = typeof(decimal).GetField("lo", BindingFlags.NonPublic);
|
44 | 43 | dec_mid = typeof(decimal).GetField("mid", BindingFlags.NonPublic);
|
45 | 44 | dec_hi = typeof(decimal).GetField("hi", BindingFlags.NonPublic);
|
46 | 45 | dec_flags = typeof(decimal).GetField("flags", BindingFlags.NonPublic);
|
| 46 | + |
| 47 | + for (int i = 0; i < 10; i++) |
| 48 | + { |
| 49 | + listPool.Enqueue(new List<object>()); |
| 50 | + } |
47 | 51 | }
|
48 | 52 |
|
49 |
| - private object[] collect; |
| 53 | + private List<object> collect = null; |
| 54 | + private bool tempAlloc = false; |
50 | 55 | private readonly int bufferSize;
|
51 | 56 | private int collectCount = 0;
|
52 | 57 |
|
53 | 58 | /// <summary>
|
54 | 59 | /// Allocates a new binary collector.
|
55 | 60 | /// </summary>
|
56 |
| - public BitWiter(int bufferSize) |
| 61 | + public BitWriter() |
57 | 62 | {
|
58 |
| - this.bufferSize = bufferSize; |
59 |
| - for (int i = expired.Count - 1; i >= 0; --i) |
60 |
| - if (expired[i].IsAlive) |
61 |
| - { |
62 |
| - collect = (object[])expired[i].Target; |
63 |
| - if (collect.Length >= bufferSize) |
64 |
| - { |
65 |
| - expired.RemoveAt(i); // This entry he been un-expired for now |
66 |
| - break; |
67 |
| - } |
68 |
| - } |
69 |
| - else expired.RemoveAt(i); // Entry has been collected by GC |
70 |
| - if (collect == null || collect.Length < bufferSize) |
71 |
| - collect = new object[bufferSize]; |
| 63 | + if (listPool.Count == 0) |
| 64 | + { |
| 65 | + Debug.LogWarning("MLAPI: There can be no more than 10 BitWriters. Have you forgotten do dispose? (It will still work with worse performance)"); |
| 66 | + collect = new List<object>(); |
| 67 | + tempAlloc = true; |
| 68 | + } |
| 69 | + else |
| 70 | + { |
| 71 | + collect = listPool.Dequeue(); |
| 72 | + } |
72 | 73 | }
|
73 | 74 |
|
74 | 75 | private void Push<T>(T b)
|
75 | 76 | {
|
76 | 77 | if (b is string || b.GetType().IsArray || IsSupportedType(b.GetType()))
|
77 |
| - collect[collectCount++] = b is string ? Encoding.UTF8.GetBytes(b as string) : b as object; |
| 78 | + collect.Add(b is string ? Encoding.UTF8.GetBytes(b as string) : b as object); |
78 | 79 | //else
|
79 | 80 | // Debug.LogWarning("MLAPI: The type \"" + b.GetType() + "\" is not supported by the Binary Serializer. It will be ignored");
|
80 | 81 | }
|
@@ -122,7 +123,7 @@ public long Finalize(ref byte[] buffer)
|
122 | 123 | foreach (var item in collect)
|
123 | 124 | Serialize(item, buffer, ref bitOffset);
|
124 | 125 |
|
125 |
| - return (bitCount / 8) + (bitCount % 8 == 0 ? 0 : 1)); |
| 126 | + return (bitCount / 8) + (bitCount % 8 == 0 ? 0 : 1); |
126 | 127 | }
|
127 | 128 |
|
128 | 129 | public long GetFinalizeSize()
|
@@ -367,8 +368,12 @@ private static long GetBitAllocation(Type t) =>
|
367 | 368 | // Creates a weak reference to the allocated collector so that reuse may be possible
|
368 | 369 | public void Dispose()
|
369 | 370 | {
|
370 |
| - expired.Add(new WeakReference(collect)); |
371 |
| - collect = null; |
| 371 | + if (!tempAlloc) |
| 372 | + { |
| 373 | + collect.Clear(); |
| 374 | + listPool.Enqueue(collect); |
| 375 | + } |
| 376 | + collect = null; //GC picks this |
372 | 377 | }
|
373 | 378 | }
|
374 | 379 | }
|
0 commit comments