using System.Buffers;
using System.Runtime.CompilerServices;
namespace NewLife.Buffers;
/// <summary>æ•°ç»„æ± ç¼“å†²å¥æŸ„ã€‚ä»Žæ± ä¸å€Ÿå‡ºç¼“冲区,离开 using 作用域自动归还</summary>
/// <remarks>
/// <para>借出请用 <see cref="Collections.Pool.Rent(Int32)"/>;调用处用 <c>var</c> 接收å³å¯ï¼Œä¸å¿…写类型å。</para>
/// <para>用于替代 <c>var buffer = pool.Rent(size); try { ... } finally { pool.Return(buffer); }</c> è¿™å¥—æ ·æ¿ä»£ç 。</para>
/// <para><b>零分é…</b>ï¼šæœ¬ç±»åž‹ä¸ºæ ˆä¸Šç±»åž‹ï¼Œå€Ÿå‡ºä¸Žå½’è¿˜å…¨ç¨‹ä¸äº§ç”Ÿå †åˆ†é…(对比 <see cref="Data.OwnerPacket"/> æ¯æ¬¡å€Ÿç”¨éœ€è¦ä¸¤ä¸ªå¯¹è±¡ï¼‰ã€‚</para>
/// <para><b>åªèƒ½åŒæ¥ä½¿ç”¨</b>ï¼šæ ˆä¸Šç±»åž‹ä¸å…许进入 async 方法ã€ä¸å…许å˜å…¥å—段ã€ä¸å…许被 lambda æ•获,编译器会直接报错。
/// async 方法内借出缓冲,请继ç»ä½¿ç”¨ try/finally。</para>
/// <para><b>使用纪律</b>ï¼šå¥æŸ„ä¸å¯å¤åˆ¶åŽåˆ†å¼€ä½¿ç”¨ï¼ˆåŽŸä»¶ä¸Žå¤åˆ¶å“都会归还åŒä¸€ä¸ªæ•°ç»„ï¼Œé€ æˆæ± 内åŒä¸€å—缓冲被两次借用);
/// <see cref="Buffer"/> å°±æ˜¯å€Ÿå‡ºçš„æ•°ç»„æœ¬èº«ï¼Œç”Ÿå‘½å‘¨æœŸä¸Žå¥æŸ„绑定,出了 using 作用域它已归还,ä¸èƒ½å†è¯»å†™ã€‚</para>
/// <para><b>长度è¯ä¹‰</b>:<see cref="Length"/> 与 <see cref="Span"/> å‡ä¸º<b>请求长度</b>ï¼ˆå€Ÿå‡ºæ—¶ä¼ å…¥çš„ size),
/// æ± å®žé™…è¿”å›žçš„æ•°ç»„å¯èƒ½æ›´é•¿ï¼Œåªåœ¨ <see cref="Buffer"/> / éšå¼è½¬æ¢ä¸Šä½“现。</para>
/// <para><b>与 <see cref="Data.OwnerPacket"/> 的分工</b>:本类型是å•奿Ÿ„ã€æŒ‰ä½œç”¨åŸŸå½’还的轻é‡å€Ÿç”¨ï¼Œä¸åšå¼•用计数ã€ä¸æ”¯æŒåˆ‡ç‰‡å…±äº«ï¼›
/// 需è¦è·¨çº¿ç¨‹/è·¨ await 共享åŒä¸€å—å†…å˜æ—¶ä½¿ç”¨ <see cref="Data.OwnerPacket"/>。</para>
/// </remarks>
/// <example>
/// <code>
/// using var buffer = Pool.Rent(1472);
/// var count = stream.Read(buffer, 0, buffer.Length);
/// </code>
/// </example>
/// <typeparam name="T">å…ƒç´ ç±»åž‹</typeparam>
public readonly ref struct PoolBuffer<T>
{
#region 属性
/// <summary>å€Ÿå‡ºå®ƒçš„æ•°ç»„æ± ã€‚null 表示默认实例(未借出任何缓冲)</summary>
private readonly ArrayPool<T>? _pool;
/// <summary>æ± å®žé™…è¿”å›žçš„æ•°ç»„ï¼Œé•¿åº¦ä¸å°äºŽè¯·æ±‚长度</summary>
private readonly T[]? _buffer;
/// <summary>è¯·æ±‚çš„å…ƒç´ æ•°é‡</summary>
private readonly Int32 _length;
/// <summary>æ± å®žé™…è¿”å›žçš„æ•°ç»„ï¼Œé•¿åº¦ä¸å°äºŽè¯·æ±‚长度;默认实例(未借出)时为 null</summary>
/// <remarks>åªç»™â€œåªæŽ¥å—数组â€çš„下游 API 用(如旧框架的 Stream.Read/Writeã€Socket.SendTo/ReceiveFromã€IOControlã€crypto å˜æ¢ï¼‰ã€‚</remarks>
public T[] Buffer => _buffer!;
/// <summary>è¯·æ±‚çš„å…ƒç´ æ•°é‡ã€‚ç‰äºŽå€Ÿå‡ºæ—¶è¯·æ±‚的长度,ä¸å—æ± å®žé™…è¿”å›žé•¿åº¦å½±å“;默认实例为 0</summary>
public Int32 Length => _length;
/// <summary>借出缓冲区的å¯å†™è§†å›¾ï¼Œé•¿åº¦ç‰äºŽè¯·æ±‚é•¿åº¦ï¼ˆæ± è¿”å›žæ›´é•¿æ—¶ä¹Ÿä¸ç¢°å¤šå‡ºæ¥çš„部分)。默认实例为空跨度</summary>
public Span<T> Span => _buffer == null ? default : _buffer.AsSpan(0, _length);
/// <summary>èŽ·å–æˆ–设置指定ä½ç½®çš„å…ƒç´ ï¼Œç›´æŽ¥ä½œç”¨äºŽæ± å®žé™…è¿”å›žçš„æ•°ç»„</summary>
/// <param name="index">å…ƒç´ ç´¢å¼•</param>
/// <returns>å…ƒç´ å¼•ç”¨</returns>
/// <remarks>索引范围是数组长度,æ£å¸¸ä½¿ç”¨ä¸è¦è¶Šè¿‡ <see cref="Length"/>。</remarks>
public ref T this[Int32 index] => ref _buffer![index];
/// <summary>转æ¢ä¸ºå€Ÿå‡ºçš„æ•°ç»„ï¼Œä¾¿äºŽç›´æŽ¥æŠŠå¥æŸ„当作数组实å‚ä¼ å…¥</summary>
/// <param name="buffer">ç¼“å†²å¥æŸ„</param>
public static implicit operator T[](PoolBuffer<T> buffer) => buffer._buffer!;
#endregion
#region æž„é€
/// <summary>å®žä¾‹åŒ–ç¼“å†²å¥æŸ„。请通过 <see cref="Collections.Pool.Rent(Int32)"/> 借出,ä¸è¦æ‰‹å·¥æž„é€ </summary>
/// <param name="pool">æ•°ç»„æ± </param>
/// <param name="buffer">æ± è¿”å›žçš„æ•°ç»„</param>
/// <param name="length">è¯·æ±‚çš„å…ƒç´ æ•°é‡</param>
internal PoolBuffer(ArrayPool<T> pool, T[] buffer, Int32 length)
{
_pool = pool;
_buffer = buffer;
_length = length;
}
#endregion
#region 方法
/// <summary>å½’è¿˜ç¼“å†²åŒºåˆ°æ•°ç»„æ± ã€‚é»˜è®¤å®žä¾‹ï¼ˆæœªå€Ÿå‡ºï¼‰ä¸ºç©ºæ“作</summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Dispose() => _pool?.Return(_buffer!);
#endregion
}
|