using System.Collections.Generic; namespace GbsPlayer { internal class ByteBufferPool { private readonly int _minBufferSize; private readonly int _maxBuffers; public int FreeAmount { get { return _freeBuffers.Count; } } private readonly List _freeBuffers; public ByteBufferPool(int minBufferSize = 0, int maxBuffers = int.MaxValue) { _minBufferSize = minBufferSize; _maxBuffers = maxBuffers; _freeBuffers = new List(); } /// /// Get a buffer that is at least as big as size. /// public byte[] Get(int size) { if (size < _minBufferSize) size = _minBufferSize; byte[] result; lock (_freeBuffers) { var index = FirstLargerThan(size); if (index == -1) { if (_freeBuffers.Count > 0) _freeBuffers.RemoveAt(0); result = new byte[size]; } else { result = _freeBuffers[index]; _freeBuffers.RemoveAt(index); } } return result; } /// /// Return the given buffer to the pool. /// public void Return(byte[] buffer) { lock (_freeBuffers) { if (FreeAmount >= _maxBuffers) return; var index = FirstLargerThan(buffer.Length); if (index == -1) _freeBuffers.Add(buffer); else _freeBuffers.Insert(index, buffer); } } // Find the smallest buffer that is larger than or equally large as size or -1 if none exist private int FirstLargerThan(int size) { if (_freeBuffers.Count == 0) return -1; var l = 0; var r = _freeBuffers.Count - 1; while (l <= r) { var m = (l + r) / 2; var buffer = _freeBuffers[m]; if (buffer.Length < size) { l = m + 1; } else if (buffer.Length > size) { r = m; if (l == r) return l; } else { return m; } } return -1; } } }