⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 payloadmanager.cs

📁 rudp可靠保障得udp传输
💻 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 + -