diff --git a/Assets/FishNet/Runtime/Serializing/WriterPool.cs b/Assets/FishNet/Runtime/Serializing/WriterPool.cs index 7a6b85e6..d3b5a852 100644 --- a/Assets/FishNet/Runtime/Serializing/WriterPool.cs +++ b/Assets/FishNet/Runtime/Serializing/WriterPool.cs @@ -89,6 +89,14 @@ public static PooledWriter Retrieve(NetworkManager networkManager, int length) PooledWriter result; // There is already one pooled. if (_lengthPool.TryGetValue(index, out stack) && stack.TryPop(out result)) + { + if (stack.Count == 0) + _lengthPool.Remove(index); + + result.Clear(networkManager); + } + // There is a larger writer pooled. + else if (TryPopLengthWriterAbove(index, out result)) { result.Clear(networkManager); } @@ -107,6 +115,46 @@ public static PooledWriter Retrieve(NetworkManager networkManager, int length) return result; } + /// + /// Tries to pop the closest writer from a bucket above minimum index. + /// + private static bool TryPopLengthWriterAbove(int minimumIndex, out PooledWriter writer) + { + int foundIndex = int.MaxValue; + Stack foundStack = null; + + foreach (KeyValuePair> entry in _lengthPool) + { + if (entry.Key <= minimumIndex) + continue; + if (entry.Value.Count == 0) + continue; + if (entry.Key < foundIndex) + { + foundIndex = entry.Key; + foundStack = entry.Value; + } + } + + if (foundStack == null) + { + writer = null; + return false; + } + + bool popped = foundStack.TryPop(out writer); + if (!popped) + { + writer = null; + return false; + } + + if (foundStack.Count == 0) + _lengthPool.Remove(foundIndex); + + return true; + } + /// /// Returns a writer to the appropriate length pool. /// Writers must be a minimum of 1000 bytes in length to be sorted by length.