mirror of
https://gitee.com/ThingsGateway/ThingsGateway.git
synced 2025-10-24 12:20:28 +08:00
125 lines
3.9 KiB
C#
125 lines
3.9 KiB
C#
#if NETFRAMEWORK || NETSTANDARD2_0
|
||
using ValueTask = System.Threading.Tasks.Task;
|
||
#endif
|
||
|
||
namespace ThingsGateway.NewLife.Buffers;
|
||
|
||
/// <summary>池化缓冲区写入器</summary>
|
||
public sealed class PooledByteBufferWriter : IBufferWriter<Byte>, IDisposable
|
||
{
|
||
#region 属性
|
||
private Byte[] _rentedBuffer;
|
||
private Int32 _index;
|
||
|
||
/// <summary>已写入内存</summary>
|
||
public ReadOnlyMemory<Byte> WrittenMemory => _rentedBuffer.AsMemory(0, _index);
|
||
|
||
/// <summary>容量</summary>
|
||
public Int32 Capacity => _rentedBuffer.Length;
|
||
#endregion
|
||
|
||
#region 构造
|
||
/// <summary>指定初始容量并初始化写入器</summary>
|
||
/// <param name="initialCapacity"></param>
|
||
public PooledByteBufferWriter(Int32 initialCapacity)
|
||
{
|
||
_rentedBuffer = ArrayPool<Byte>.Shared.Rent(initialCapacity);
|
||
_index = 0;
|
||
}
|
||
|
||
/// <summary>销毁。释放内存并返回池里</summary>
|
||
public void Dispose()
|
||
{
|
||
if (_rentedBuffer != null)
|
||
ClearAndReturnBuffers();
|
||
}
|
||
#endregion
|
||
|
||
#region 方法
|
||
/// <summary>初始化空实例</summary>
|
||
/// <param name="initialCapacity"></param>
|
||
public void InitializeEmptyInstance(Int32 initialCapacity)
|
||
{
|
||
_rentedBuffer = ArrayPool<Byte>.Shared.Rent(initialCapacity);
|
||
_index = 0;
|
||
}
|
||
|
||
/// <summary>清空写入器</summary>
|
||
public void Clear()
|
||
{
|
||
_rentedBuffer.AsSpan(0, _index).Clear();
|
||
_index = 0;
|
||
}
|
||
|
||
/// <summary>清空写入器并归还到对象池</summary>
|
||
public void ClearAndReturnBuffers()
|
||
{
|
||
Clear();
|
||
|
||
var rentedBuffer = _rentedBuffer;
|
||
_rentedBuffer = null!;
|
||
ArrayPool<Byte>.Shared.Return(rentedBuffer);
|
||
}
|
||
|
||
/// <summary>通知 IBufferWriter,已向输出写入 count 数据项。</summary>
|
||
/// <param name="count"></param>
|
||
public void Advance(Int32 count) => _index += count;
|
||
|
||
/// <summary>返回要向其中写入数据的 Memory,且大小至少是 sizeHint 指定的请求大小。</summary>
|
||
/// <param name="sizeHint"></param>
|
||
/// <returns></returns>
|
||
public Memory<Byte> GetMemory(Int32 sizeHint = 256)
|
||
{
|
||
CheckAndResizeBuffer(sizeHint);
|
||
return _rentedBuffer.AsMemory(_index);
|
||
}
|
||
|
||
/// <summary>返回要向其中写入数据的 Span,且大小至少是 sizeHint 指定的请求大小。</summary>
|
||
/// <param name="sizeHint"></param>
|
||
/// <returns></returns>
|
||
public Span<Byte> GetSpan(Int32 sizeHint = 256)
|
||
{
|
||
CheckAndResizeBuffer(sizeHint);
|
||
return _rentedBuffer.AsSpan(_index);
|
||
}
|
||
|
||
/// <summary>写入到数据流</summary>
|
||
/// <param name="destination"></param>
|
||
/// <param name="cancellationToken"></param>
|
||
/// <returns></returns>
|
||
public ValueTask WriteToStreamAsync(Stream destination, CancellationToken cancellationToken) => destination.WriteAsync(WrittenMemory, cancellationToken);
|
||
|
||
/// <summary>写入到数据流</summary>
|
||
/// <param name="destination"></param>
|
||
public void WriteToStream(Stream destination) => destination.Write(_rentedBuffer, 0, _index);
|
||
|
||
private void CheckAndResizeBuffer(Int32 sizeHint)
|
||
{
|
||
var num = _rentedBuffer.Length;
|
||
var num2 = num - _index;
|
||
if (_index >= 1073741795)
|
||
{
|
||
sizeHint = Math.Max(sizeHint, 2147483591 - num);
|
||
}
|
||
if (sizeHint <= num2) return;
|
||
|
||
var num3 = Math.Max(sizeHint, num);
|
||
var num4 = num + num3;
|
||
if ((UInt32)num4 > 2147483591u)
|
||
{
|
||
num4 = num + sizeHint;
|
||
if ((UInt32)num4 > 2147483591u)
|
||
{
|
||
throw new OutOfMemoryException($"BufferMaximumSizeExceeded({num4})");
|
||
}
|
||
}
|
||
var rentedBuffer = _rentedBuffer;
|
||
_rentedBuffer = ArrayPool<Byte>.Shared.Rent(num4);
|
||
var span = rentedBuffer.AsSpan(0, _index);
|
||
span.CopyTo(_rentedBuffer);
|
||
span.Clear();
|
||
ArrayPool<Byte>.Shared.Return(rentedBuffer);
|
||
}
|
||
#endregion
|
||
}
|