📄 payloadmanager.cs
字号:
//#define COUNT_ALLOCATIONS
//#define SIMPLE_ALLOCATION
using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using System.Threading;
using Helper.Threading.Collections;
namespace Helper.Net.RUDP
{
/// <summary>
/// Manage the allocation of the payloads. It is done like this because
/// we always use the same payload size.
///
/// So it is better to reuse memory blocks.
/// </summary>
static internal class PayloadManager
{
#region Variables
static LockFreeQueue<WeakReference>[] _blocks = new LockFreeQueue<WeakReference>[156 + 1];
#if COUNT_ALLOCATIONS
static int _countAllocate = 0;
static int _countDeallocate = 0;
#endif
#endregion
#region Constructor
static PayloadManager()
{
foreach (int index in Enum.GetValues(typeof(RUDPPacketChannel)))
_blocks[index] = new LockFreeQueue<WeakReference>();
}
#endregion
#region Allocate
static public byte[] Allocate(RUDPPacketChannel channel, int size)
{
#if SIMPLE_ALLOCATION
return new byte[size];
#else
WeakReference weak;
byte[] block = null;
#if COUNT_ALLOCATIONS
Interlocked.Increment(ref _countAllocate);
#endif
//---- Get a memory block
if (!_blocks[(int)channel].TryDequeue(out weak))
{
byte[] buffer;
for (int index = 0; index < 10; index++)
{
buffer = new byte[size];
// ask the garbage collector to avoid from relocating a certain object in memory
System.Runtime.InteropServices.GCHandle.Alloc(buffer, System.Runtime.InteropServices.GCHandleType.Pinned);
//GC.KeepAlive(buffer);
_blocks[(int)channel].Enqueue(new WeakReference(buffer));
}
buffer = new byte[size];
System.Runtime.InteropServices.GCHandle.Alloc(buffer, System.Runtime.InteropServices.GCHandleType.Pinned);
//GC.KeepAlive(buffer);
return buffer;
}
if (weak.IsAlive)
block = (byte[])weak.Target;
if (block == null)
return Allocate(channel, size);
// Only usefull when MTU change
if (block.Length != size)
Array.Resize<byte>(ref block, size);
return block;
#endif
}
#endregion
#region Deallocate
static public void Deallocate(RUDPPacketChannel channel, byte[] block)
{
#if !SIMPLE_ALLOCATION
//---- For the right channel
LockFreeQueue<WeakReference> blockSet = _blocks[(int)channel];
blockSet.Enqueue(new WeakReference(block));
#if COUNT_ALLOCATIONS
Interlocked.Increment(ref _countDeallocate);
#endif
#endif
}
#endregion
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -