接受到的数据,使用环绕缓冲区来解决粘包和半包的处理
/// <summary>
/// 接受到的数据,使用环绕缓冲区来解决粘包和半包的处理
/// </summary>
[MultiThreadedSupport( "zh-CHS", "当前的类所有成员都可锁定,支持多线程操作" )]
public class ReceiveQueue
{
#region zh-CHS 类常量 | en Class Constants
/// <summary>
/// 字节默认的大小
/// </summary>
private const long BUFFER_SIZE = 2048;
#endregion
#region zh-CHS 私有成员变量 | en Private Member Variables
/// <summary>
/// 字节的头位置
/// </summary>
private long m_Head = 0;
/// <summary>
/// 字节的尾位置
/// </summary>
private long m_Tail = 0;
/// <summary>
/// 字节的数组
/// </summary>
private byte[] m_Buffer = new byte[BUFFER_SIZE];
/// <summary>
///
/// </summary>
private SpinLock m_LockBuffer = new SpinLock();
#endregion
#region zh-CHS 属性 | en Properties
#region zh-CHS 私有成员变量 | en Private Member Variables
/// <summary>
/// 字节的大小
/// </summary>
private long m_Size = 0;
#endregion
/// <summary>
/// 环绕缓冲区内的数据大小
/// </summary>
public long Length
{
get { return m_Size; }
}
#endregion
#region zh-CHS 方法 | en Method
/// <summary>
/// 给出使用环绕缓冲区内的数据
/// </summary>
/// <param name="byteBuffer"></param>
/// <param name="iOffset"></param>
/// <param name="iSize"></param>
/// <returns>返回实际读取到的字节数</returns>
public long Dequeue( ref byte[] byteBuffer, long iOffset, long iSize )
{
if ( iSize == 0 )
return 0;
if ( iSize > m_Size )
iSize = m_Size;
m_LockBuffer.Enter();
{
if ( m_Head < m_Tail )
Buffer.BlockCopy( m_Buffer, (int)m_Head, byteBuffer, (int)iOffset, (int)iSize );
else
{
long rightLength = m_Buffer.Length - m_Head;
if ( rightLength >= iSize )
Buffer.BlockCopy( m_Buffer, (int)m_Head, byteBuffer, (int)iOffset, (int)iSize );
else
{
Buffer.BlockCopy( m_Buffer, (int)m_Head, byteBuffer, (int)iOffset, (int)rightLength );
Buffer.BlockCopy( m_Buffer, 0, byteBuffer, (int)( iOffset + rightLength ), (int)( iSize - rightLength ) );
}
}
m_Head = ( m_Head + iSize ) % m_Buffer.Length;
m_Size -= iSize;
if ( m_Size == 0 )
{
m_Head = 0;
m_Tail = 0;
}
}
m_LockBuffer.Exit();
return iSize;
}
/// <summary>
/// 压入数据至环绕缓冲区内
/// </summary>
/// <param name="byteBuffer"></param>
/// <param name="iOffset"></param>
/// <param name="iSize"></param>
public void Enqueue( byte[] byteBuffer, long iOffset, long iSize )
{
m_LockBuffer.Enter();
{
if ( ( m_Size + iSize ) > m_Buffer.Length )
SetCapacity( ( m_Size + iSize + 2047 ) & ~2047 ); // 总是以2048的倍数来增大字节数, :( 弄得我老半天才明白原理呢!
if ( m_Head < m_Tail )
{
long rightLength = m_Buffer.Length - m_Tail;
if ( rightLength >= iSize )
Buffer.BlockCopy( byteBuffer, (int)iOffset, m_Buffer, (int)m_Tail, (int)iSize );
else
{
Buffer.BlockCopy( byteBuffer, (int)iOffset, m_Buffer, (int)m_Tail, (int)rightLength );
Buffer.BlockCopy( byteBuffer, (int)( iOffset + rightLength ), m_Buffer, 0, (int)( iSize - rightLength ) );
}
}
else
Buffer.BlockCopy( byteBuffer, (int)iOffset, m_Buffer, (int)m_Tail, (int)iSize );
m_Tail = ( m_Tail + iSize ) % m_Buffer.Length;
m_Size += iSize;
}
m_LockBuffer.Exit();
}
/// <summary>
/// 压入数据至环绕缓冲区内
/// </summary>
/// <param name="byteBuffer"></param>
/// <param name="iOffset"></param>
/// <param name="iSize"></param>
public void Enqueue( IntPtr byteBuffer, long iOffset, long iSize )
{
m_LockBuffer.Enter();
{
if ( ( m_Size + iSize ) > m_Buffer.Length )
SetCapacity( ( m_Size + iSize + 2047 ) & ~2047 ); // 总是以2048的倍数来增大字节数, :( 弄得我我半天才明白原理呢!
IntPtr byteBufferOffset;
if ( m_Head < m_Tail )
{
long rightLength = m_Buffer.Length - m_Tail;
if ( rightLength >= iSize )
{
byteBufferOffset = new IntPtr( byteBuffer.ToInt64() + iOffset );
Marshal.Copy( byteBufferOffset, m_Buffer, (int)m_Tail, (int)iSize );
}
else
{
byteBufferOffset = new IntPtr( byteBuffer.ToInt64() + iOffset );
Marshal.Copy( byteBuffer, m_Buffer, (int)m_Tail, (int)rightLength );
byteBufferOffset = new IntPtr( byteBuffer.ToInt64() + iOffset + rightLength );
Marshal.Copy( byteBuffer, m_Buffer, 0, (int)( iSize - rightLength ) );
}
}
else
{
byteBufferOffset = new IntPtr( byteBuffer.ToInt64() + iOffset );
Marshal.Copy( byteBuffer, m_Buffer, (int)m_Tail, (int)iSize );
}
m_Tail = ( m_Tail + iSize ) % m_Buffer.Length; // 返回环绕的数据的位置
m_Size += iSize;
}
m_LockBuffer.Exit();
}
/// <summary>
/// 清除数据的信息,不清除数据缓冲,用于下次使用
/// </summary>
public void Clear()
{
m_LockBuffer.Enter();
{
m_Head = 0;
m_Tail = 0;
m_Size = 0;
}
m_LockBuffer.Exit();
}
/// <summary>
/// 给出数据包的长度
/// </summary>
/// <returns></returns>
public long GetPacketLength()
{
long iReturn = 0;
m_LockBuffer.Enter();
{
EventHandler<PacketLengthInfoEventArgs> tempEvent = s_ThreadEventPacketLength;
if ( tempEvent != null )
{
PacketLengthInfoEventArgs packetLengthInfoEventArgs = new PacketLengthInfoEventArgs( m_Buffer, m_Size, m_Head );
tempEvent( this, packetLengthInfoEventArgs );
iReturn = packetLengthInfoEventArgs.PacketLength;
}
}
m_LockBuffer.Exit();
return iReturn;
}
/// <summary>
/// 给出数据包的ID
/// </summary>
/// <returns></returns>
public long GetPacketID()
{
long iReturn = 0;
m_LockBuffer.Enter();
{
EventHandler<PacketIdInfoEventArgs> tempEvent = s_ThreadEventPacketID;
if ( tempEvent != null )
{
PacketIdInfoEventArgs packetIdInfoEventArgs = new PacketIdInfoEventArgs( m_Buffer, m_Size, m_Head );
tempEvent( this, packetIdInfoEventArgs );
iReturn = packetIdInfoEventArgs.PacketId;
}
}
m_LockBuffer.Exit();
return iReturn;
}
/// <summary>
/// 给出数据包的ID
/// </summary>
/// <returns></returns>
public PacketHeadT GetPacketHead<PacketHeadT>( EventHandler<PacketHeadInfoEventArgs<PacketHeadT>> eventHandler )
{
if ( eventHandler == null )
throw new Exception( "ReceiveQueue.GetPacketHead<.>(...) - eventHandler == null error!" );
PacketHeadT returnT = default( PacketHeadT );
m_LockBuffer.Enter();
{
PacketHeadInfoEventArgs<PacketHeadT> eventArgs = new PacketHeadInfoEventArgs<PacketHeadT>( m_Buffer, m_Size, m_Head );
eventHandler( this, eventArgs );
returnT = eventArgs.PacketHead;
}
m_LockBuffer.Exit();
return returnT;
}
#endregion
#region zh-CHS 内部方法 | en Internal Methods
#region zh-CHS 私有成员变量 | en Private Member Variables
/// <summary>
/// 当前的类是否已锁
/// </summary>
private LockInOut m_bIsLockThis = new LockInOut( false );
#endregion
/// <summary>
/// 锁定当前的类(表示当前类正在调用中)
/// </summary>
/// <returns>返回是否已经锁定成功</returns>
internal bool InProcessReceive()
{
return m_bIsLockThis.InLock();
}
/// <summary>
/// 释放当前已经锁定的类(表示当前类的调用已结束)
/// </summary>
internal void OutProcessReceive()
{
m_bIsLockThis.OutLock();
}
#endregion
#region zh-CHS 私有方法 | en Private Method
/// <summary>
/// 扩大缓冲数据的大小(当前都在锁中操作,因此不需要锁定的)
/// </summary>
/// <param name="iCapacity"></param>
private void SetCapacity( long iCapacity )
{
byte[] newBuffer = new byte[iCapacity];
if ( m_Size > 0 )
{
if ( m_Head < m_Tail )
Buffer.BlockCopy( m_Buffer, (int)m_Head, newBuffer, 0, (int)m_Size );
else
{
Buffer.BlockCopy( m_Buffer, (int)m_Head, newBuffer, 0, (int)( m_Buffer.Length - m_Head ) );
Buffer.BlockCopy( m_Buffer, 0, newBuffer, (int)( m_Buffer.Length - m_Head ), (int)m_Tail );
}
}
m_Head = 0;
m_Tail = m_Size;
m_Buffer = newBuffer;
}
#endregion
#region zh-CHS 共有事件 | en Public Event
#region zh-CHS 私有成员变量 | en Private Member Variables
/// <summary>
///
/// </summary>
private EventHandler<PacketLengthInfoEventArgs> s_ThreadEventPacketLength;
/// <summary>
///
/// </summary>
private SpinLock s_LockThreadEventPacketLength = new SpinLock();
#endregion
/// <summary>
/// 获取接收到的数据包长度
/// </summary>
public event EventHandler<PacketLengthInfoEventArgs> ThreadEventPacketLength
{
add
{
s_LockThreadEventPacketLength.Enter();
{
s_ThreadEventPacketLength += value;
}
s_LockThreadEventPacketLength.Exit();
}
remove
{
s_LockThreadEventPacketLength.Enter();
{
s_ThreadEventPacketLength -= value;
}
s_LockThreadEventPacketLength.Exit();
}
}
#region zh-CHS 私有成员变量 | en Private Member Variables
/// <summary>
///
/// </summary>
private EventHandler<PacketIdInfoEventArgs> s_ThreadEventPacketID;
/// <summary>
///
/// </summary>
private SpinLock s_LockThreadEventPacketID = new SpinLock();
#endregion
/// <summary>
/// 获取接收到的数据包长度
/// </summary>
public event EventHandler<PacketIdInfoEventArgs> ThreadEventPacketID
{
add
{
s_LockThreadEventPacketID.Enter();
{
s_ThreadEventPacketID += value;
}
s_LockThreadEventPacketID.Exit();
}
remove
{
s_LockThreadEventPacketID.Enter();
{
s_ThreadEventPacketID -= value;
}
s_LockThreadEventPacketID.Exit();
}
}
#endregion
}
发送字节缓存
/// <summary>
///
/// </summary>
internal struct SendBuffer
{
#region zh-CHS 共有常量 | en Public Constants
/// <summary>
///
/// </summary>
public readonly static SendBuffer NullBuffer = new SendBuffer( null );
#endregion
#region zh-CHS 构造和初始化和清理 | en Constructors and Initializers and Dispose
/// <summary>
/// 私有的构造类
/// </summary>
private SendBuffer( byte[] buffer )
{
m_Buffer = buffer;
m_Length = 0;
}
#endregion
#region zh-CHS 属性 | en Properties
#region zh-CHS 私有成员变量 | en Private Member Variables
/// <summary>
/// 缓冲区的字节
/// </summary>
private byte[] m_Buffer;
#endregion
/// <summary>
/// 缓冲区的字节
/// </summary>
public byte[] Buffer
{
get { return m_Buffer; }
}
#region zh-CHS 私有成员变量 | en Private Member Variables
/// <summary>
/// 缓冲区的长度
/// </summary>
private long m_Length;
#endregion
/// <summary>
/// 缓冲区已写入的长度
/// </summary>
public long Length
{
get { return m_Length; }
}
/// <summary>
/// 缓冲区的剩余的有效空间
/// </summary>
public long SpareSpace
{
get { return ( m_Buffer.Length - m_Length ); }
}
/// <summary>
/// 缓冲区是否已经满了
/// </summary>
public bool IsFull
{
get { return ( m_Length >= m_Buffer.Length ); }
}
/// <summary>
///
/// </summary>
public bool IsNull
{
get { return m_Buffer == null; }
}
#endregion
#region zh-CHS 方法 | en Method
/// <summary>
///
/// </summary>
/// <param name="byteBuffer"></param>
/// <param name="iOffset"></param>
/// <param name="iLength"></param>
/// <returns></returns>
public long Write( byte[] byteBuffer, long lOffset, long lLength )
{
// 获取可以写当前缓冲区的字节数
long iWrite = Math.Min( lLength, this.SpareSpace );
// 写入数据
System.Buffer.BlockCopy( byteBuffer, (int)lOffset, m_Buffer, (int)m_Length, (int)iWrite );
// 跟新缓冲区的长度
m_Length += iWrite;
return iWrite;
}
/// <summary>
///
/// </summary>
public void Release()
{
if ( m_Buffer == null )
return;
// 把数据返回进内存池
SendQueue.ReleaseBuffer( m_Buffer );
m_Buffer = null;
m_Length = 0;
}
#endregion
#region zh-CHS 静态方法 | en Static Method
/// <summary>
/// 请求Gram类
/// </summary>
/// <returns></returns>
public static SendBuffer Instance()
{
return new SendBuffer( SendQueue.AcquireBuffer() );
}
#endregion
}
/// <summary>
/// 数据输出包的缓冲区,如果数据过长就等处理缓存发送时发送数据( 小于 512K 时 )
/// 之所以小于 512K 是因为TCP-IP发送数据时总是发送至客户端彼此确认完毕后才通知返回的,如果过大网络延迟时会严重影响网络的通讯.
/// </summary>
[MultiThreadedSupport( "zh-CHS", "当前的类所有成员都可锁定,支持多线程操作" )]
internal class SendQueue
{
#region zh-CHS 私有成员变量 | en Private Member Variables
#region zh-CHS 私有常量 | en Private Constants
/// <summary>
///
/// </summary>
private readonly static int QUEUE_CAPACITY_SIZE = 1024;
#endregion
/// <summary>
/// 当Flush发出的数据(最后发出的数据块)
/// </summary>
private SendBuffer m_FlushBuffer = SendBuffer.NullBuffer;
/// <summary>
/// 等待需要发出的数据
/// </summary>
private Queue<SendBuffer> m_PendingBuffer = new Queue<SendBuffer>( QUEUE_CAPACITY_SIZE );
/// <summary>
/// 等待需要发出的数据锁
/// </summary>
private SpinLock m_LockFlushAndPending = new SpinLock();
#endregion
#region zh-CHS 属性 | en Properties
/// <summary>
/// 当前需发送的数据是否空的
/// </summary>
public bool IsEmpty
{
get { return ( m_PendingBuffer.Count <= 0 && m_FlushBuffer.IsNull == true ); }
}
#region zh-CHS 私有成员变量 | en Private Member Variables
/// <summary>
///
/// </summary>
private long m_WaitSendSize = 0;
#endregion
/// <summary>
/// 缓冲区内还有多少没有发送的数据
/// </summary>
public long WaitSendSize
{
get { return m_WaitSendSize; }
}
#endregion
#region zh-CHS 静态属性 | en Static Properties
#region zh-CHS 私有成员变量 | en Private Member Variables
/// <summary>
/// 缓冲的数据大小
/// </summary>
private static int s_CoalesceBufferSize = 512;
#endregion
/// <summary>
/// 合并缓冲的数据大小
/// </summary>
public static int CoalesceBufferSize
{
get { return s_CoalesceBufferSize; }
set
{
if ( s_CoalesceBufferSize == value )
return;
if ( s_CoalesceBufferSize <= 0 )
return;
s_CoalesceBufferSize = value;
BufferPool tempBuffers = s_UnusedBuffers;
s_UnusedBuffers = new BufferPool( "SendQueue - CoalescedBuffer", INITIAL_CAPACITY, s_CoalesceBufferSize );
if ( tempBuffers != null )
tempBuffers.Free();
}
}
#endregion
#region zh-CHS 方法 | en Method
#region zh-CHS 私有成员变量 | en Private Member Variables
/// <summary>
/// 可能是windows操作系统的最大可发送的字节数
/// </summary>
private const int PENDING_MAX_BUFFER = 96 * 1024;
#endregion
/// <summary>
/// 如果数据满了,且缓冲区内的数据是空的则返回需要发送的数据
/// 调用Enqueue(...)后调用Dequeue(...),不能直接调用Dequeue(...)
/// </summary>
/// <param name="byteBuffer"></param>
/// <param name="iOffset"></param>
/// <param name="iLength"></param>
/// <returns></returns>
public void Enqueue( byte[] byteBuffer, long iOffset, long iLength )
{
if ( byteBuffer == null )
throw new Exception( "SendQueue.Enqueue(...) - byteBuffer == null error!" );
if ( iOffset < 0 || iOffset >= byteBuffer.Length )
throw new Exception( "SendQueue.Enqueue(...) - iOffset < 0 || iOffset >= byteBuffer.Length error!" );
if ( iLength < 0 || iLength > byteBuffer.Length ) // 如果iLength == 0就返回空,如果iLength == 0就跳过
throw new Exception( "SendQueue.Enqueue(...) - iLength < 0 || iLength > byteBuffer.Length error!" );
if ( ( byteBuffer.Length - iOffset ) < iLength )
throw new Exception( "SendQueue.Enqueue(...) - ( byteBuffer.Length - iOffset ) < iLength error!" );
m_LockFlushAndPending.Enter();
{
do
{
if ( m_FlushBuffer.IsNull == true )
{
// nothing yet buffered
m_FlushBuffer = SendBuffer.Instance();
if ( m_FlushBuffer.IsNull == true )
throw new Exception( "SendQueue.Enqueue(...) - m_FlushBuffer.IsNull == true error!" );
}
// 当前已经写入的字节
long iBytesWritten = m_FlushBuffer.Write( byteBuffer, iOffset, iLength );
iOffset += iBytesWritten;
iLength -= iBytesWritten;
// 写入需要发送的数据的大小
m_WaitSendSize += iBytesWritten;
// 如果数据没有满,且数据写入完毕则退出,返回空,不添加到集合内
if ( m_FlushBuffer.IsFull == true )
{
// 如果满了添加到集合内的尾处
m_PendingBuffer.Enqueue( m_FlushBuffer );
m_FlushBuffer = SendBuffer.NullBuffer; // 置空再次请求缓存
}
} while ( iLength > 0 );
}
m_LockFlushAndPending.Exit();
}
/// <summary>
/// 获取当前的数据
/// </summary>
/// <returns></returns>
public SendBuffer Dequeue()
{
SendBuffer sendGram = SendBuffer.NullBuffer;
m_LockFlushAndPending.Enter();
{
if ( m_PendingBuffer.Count > 0 )
{
sendGram = m_PendingBuffer.Dequeue(); // 再给出数据
}
else if ( m_FlushBuffer.IsNull == false )
{
sendGram = m_FlushBuffer; // 再给出数据
m_FlushBuffer = SendBuffer.NullBuffer;
}
// 移去已发送的数据的大小
m_WaitSendSize -= sendGram.Length;
}
m_LockFlushAndPending.Exit();
return sendGram;
}
/// <summary>
/// 清除数据
/// </summary>
public void Clear()
{
m_LockFlushAndPending.Enter();
{
while ( m_PendingBuffer.Count > 0 )
m_PendingBuffer.Dequeue().Release();
if ( m_FlushBuffer.IsNull == false )
{
m_FlushBuffer.Release();
m_FlushBuffer = SendBuffer.NullBuffer;
}
// 清空
m_WaitSendSize = 0;
}
m_LockFlushAndPending.Exit();
}
#endregion
#region zh-CHS 私有静态方法 | en Private Static Method
#region zh-CHS 私有静态成员变量 | en Private Static Member Variables
#region zh-CHS 私有常量 | en Private Constants
/// <summary>
///
/// </summary>
private readonly static int INITIAL_CAPACITY = 1024;
#endregion
/// <summary>
///
/// </summary>
private static BufferPool s_UnusedBuffers = new BufferPool( "SendQueue - CoalescedBuffer", INITIAL_CAPACITY, s_CoalesceBufferSize );
#endregion
/// <summary>
///
/// </summary>
/// <returns></returns>
internal static byte[] AcquireBuffer()
{
return s_UnusedBuffers.AcquireBuffer();
}
/// <summary>
///
/// </summary>
/// <param name="byteBuffer"></param>
internal static void ReleaseBuffer( byte[] byteBuffer )
{
Debug.Assert( byteBuffer != null, "SendQueue.ReleaseBuffer(...) - byteBuffer == null error!" );
if ( byteBuffer.Length == s_CoalesceBufferSize ) // 可能修改过m_CoalesceBufferSize如果不同就抛弃它
s_UnusedBuffers.ReleaseBuffer( byteBuffer );
}
#endregion
}
内存池
/// <summary>
/// (内存池)难得用一次泛型,C# 比 C++ 泛型好用好写多了 :)
/// </summary>
/// <typeparam name="T"></typeparam>
[MultiThreadedSupport( "zh-CHS", "当前的类所有成员都可锁定,支持多线程操作" )]
internal class MemoryPool<T> where T : new()
{
#region zh-CHS 共有的结构 | en Public Struct
/// <summary>
///
/// </summary>
public struct PoolInfo
{
#region zh-CHS 共有属性 | en Public Properties
#region zh-CHS 私有成员变量 | en Private Member Variables
/// <summary>
///
/// </summary>
private string m_strName;
#endregion
/// <summary>
///
/// </summary>
public string Name
{
get { return m_strName; }
internal set { m_strName = value; }
}
#region zh-CHS 私有成员变量 | en Private Member Variables
/// <summary>
///
/// </summary>
private int m_iFreeCount;
#endregion
/// <summary>
///
/// </summary>
public int FreeCount
{
get { return m_iFreeCount; }
internal set { m_iFreeCount = value; }
}
#region zh-CHS 私有成员变量 | en Private Member Variables
/// <summary>
///
/// </summary>
private int m_iInitialCapacity;
#endregion
/// <summary>
///
/// </summary>
public int InitialCapacity
{
get { return m_iInitialCapacity; }
internal set { m_iInitialCapacity = value; }
}
#region zh-CHS 私有成员变量 | en Private Member Variables
/// <summary>
///
/// </summary>
private int m_iCurrentCapacity;
#endregion
/// <summary>
///
/// </summary>
public int CurrentCapacity
{
get { return m_iCurrentCapacity; }
internal set { m_iCurrentCapacity = value; }
}
#region zh-CHS 私有成员变量 | en Private Member Variables
/// <summary>
///
/// </summary>
private int m_iMisses;
#endregion
/// <summary>
///
/// </summary>
public int Misses
{
get { return m_iMisses; }
internal set { m_iMisses = value; }
}
#endregion
}
#endregion
#region zh-CHS 私有成员变量 | en Private Member Variables
/// <summary>
/// 内存池的名字
/// </summary>
private string m_Name = string.Empty;
/// <summary>
/// 内存池的容量
/// </summary>
private int m_InitialCapacity = 0;
/// <summary>
/// 内存池的容量不足时再次请求数据的次数
/// </summary>
private int m_Misses = 0;
/// <summary>
/// 内存池
/// </summary>
private ConcurrentQueue<T> m_FreePool = new ConcurrentQueue<T>();
#endregion
#region zh-CHS 构造和初始化和清理 | en Constructors and Initializers and Dispose
/// <summary>
/// 初始化内存池
/// </summary>
/// <param name="strName"></param>
/// <param name="iInitialCapacity"></param>
public MemoryPool( string strName, int iInitialCapacity )
{
m_Name = strName;
m_InitialCapacity = iInitialCapacity;
for ( int iIndex = 0; iIndex < iInitialCapacity; ++iIndex )
m_FreePool.Enqueue( new T() );
}
#endregion
#region zh-CHS 共有方法 | en Public Methods
/// <summary>
/// 内存池请求数据
/// </summary>
/// <returns></returns>
public T AcquirePoolContent()
{
T returnT = default( T );
do
{
if ( m_FreePool.Count > 0 )
{
if ( m_FreePool.TryDequeue( out returnT ) == true )
break;
}
++m_Misses;
for ( int iIndex = 0; iIndex < m_InitialCapacity; ++iIndex )
m_FreePool.Enqueue( new T() );
if ( m_FreePool.TryDequeue( out returnT ) == true )
break;
} while ( true );
return returnT;
}
/// <summary>
/// 内存池释放数据
/// </summary>
/// <param name="TContent"></param>
public void ReleasePoolContent( T contentT )
{
if ( contentT == null )
throw new ArgumentNullException( "TContent", "TContent == null" );
m_FreePool.Enqueue( contentT );
}
/// <summary>
/// 释放内存池内全部的数据
/// </summary>
public void Free()
{
m_FreePool = new ConcurrentQueue<T>();
}
/// <summary>
/// 给出内存池的详细信息
/// </summary>
/// <param name="strName"></param>
/// <param name="iFreeCount"></param>
/// <param name="iInitialCapacity"></param>
/// <param name="iCurrentCapacity"></param>
/// <param name="iMisses"></param>
public MemoryPool<T>.PoolInfo GetPoolInfo()
{
MemoryPool<T>.PoolInfo poolInfo = new MemoryPool<T>.PoolInfo();
// 可以不需要锁定的,因为只是给出没有修改数据
poolInfo.Name = m_Name;
poolInfo.FreeCount = m_FreePool.Count;
poolInfo.InitialCapacity = m_InitialCapacity;
poolInfo.CurrentCapacity = m_InitialCapacity * ( 1 + m_Misses ); // m_Misses是从零开始计算的因此需加1
poolInfo.Misses = m_Misses;
return poolInfo;
}
#endregion
}
Byte的内存池
/// <summary>
/// Byte的内存池
/// </summary>
[MultiThreadedSupport( "zh-CHS", "当前的类所有成员都可锁定,支持多线程操作" )]
public class BufferPool
{
#region zh-CHS 共有的结构 | en Public Struct
/// <summary>
///
/// </summary>
public struct PoolInfo
{
#region zh-CHS 共有属性 | en Public Properties
#region zh-CHS 私有成员变量 | en Private Member Variables
/// <summary>
///
/// </summary>
private string m_strName;
#endregion
/// <summary>
///
/// </summary>
public string Name
{
get { return m_strName; }
internal set { m_strName = value; }
}
#region zh-CHS 私有成员变量 | en Private Member Variables
/// <summary>
///
/// </summary>
private long m_iBufferSize;
#endregion
/// <summary>
///
/// </summary>
public long BufferSize
{
get { return m_iBufferSize; }
internal set { m_iBufferSize = value; }
}
#region zh-CHS 私有成员变量 | en Private Member Variables
/// <summary>
///
/// </summary>
private long m_iFreeCount;
#endregion
/// <summary>
///
/// </summary>
public long FreeCount
{
get { return m_iFreeCount; }
internal set { m_iFreeCount = value; }
}
#region zh-CHS 私有成员变量 | en Private Member Variables
/// <summary>
///
/// </summary>
private long m_iInitialCapacity;
#endregion
/// <summary>
///
/// </summary>
public long InitialCapacity
{
get { return m_iInitialCapacity; }
internal set { m_iInitialCapacity = value; }
}
#region zh-CHS 私有成员变量 | en Private Member Variables
/// <summary>
///
/// </summary>
private long m_iCurrentCapacity;
#endregion
/// <summary>
///
/// </summary>
public long CurrentCapacity
{
get { return m_iCurrentCapacity; }
internal set { m_iCurrentCapacity = value; }
}
#region zh-CHS 私有成员变量 | en Private Member Variables
/// <summary>
///
/// </summary>
private long m_iMisses;
#endregion
/// <summary>
///
/// </summary>
public long Misses
{
get { return m_iMisses; }
internal set { m_iMisses = value; }
}
#endregion
}
#endregion
#region zh-CHS 私有成员变量 | en Private Member Variables
/// <summary>
/// 内存池的名字
/// </summary>
private string m_BufferName;
/// <summary>
/// 数据获取的失败次数
/// </summary>
private long m_Misses;
/// <summary>
/// 数据的大小
/// </summary>
private long m_BufferSize;
/// <summary>
/// 初始的空间大小
/// </summary>
private long m_InitialCapacity;
/// <summary>
/// 内存池
/// </summary>
private ConcurrentQueue<byte[]> m_FreeBuffers = new ConcurrentQueue<byte[]>();
#endregion
#region zh-CHS 构造和初始化和清理 | en Constructors and Initializers and Dispose
/// <summary>
/// 初始化构造
/// </summary>
/// <param name="strName"></param>
/// <param name="iInitialCapacity"></param>
/// <param name="iBufferSize"></param>
public BufferPool( string strBufferName, long iInitialCapacity, long iBufferSize )
{
m_BufferName = strBufferName;
m_BufferSize = iBufferSize;
m_InitialCapacity = iInitialCapacity;
for ( int iIndex = 0; iIndex < iInitialCapacity; ++iIndex )
m_FreeBuffers.Enqueue( new byte[iBufferSize] );
s_Pools.Add( this );
}
#endregion
#region zh-CHS 静态属性 | en Static Properties
#region zh-CHS 私有静态成员变量 | en Private Static Member Variables
/// <summary>
/// 存放全局Byte的内存列表
/// </summary>
private static SafeHashSet<BufferPool> s_Pools = new SafeHashSet<BufferPool>();
#endregion
/// <summary>
/// 存放全局Byte的内存列表
/// </summary>
public static SafeHashSet<BufferPool> GlobalPools
{
get { return s_Pools; }
}
#endregion
#region zh-CHS 方法 | en Method
/// <summary>
/// 内存池请求数据
/// </summary>
/// <returns></returns>
public byte[] AcquireBuffer()
{
byte[] returnByteArray = null;
do
{
if ( m_FreeBuffers.Count > 0 )
{
if ( m_FreeBuffers.TryDequeue( out returnByteArray ) == true )
break;
}
++m_Misses;
for ( int iIndex = 0; iIndex < m_InitialCapacity; ++iIndex )
m_FreeBuffers.Enqueue( new byte[m_BufferSize] );
if ( m_FreeBuffers.TryDequeue( out returnByteArray ) == true )
break;
} while ( true );
return returnByteArray;
}
/// <summary>
/// 内存池请释放
/// </summary>
/// <param name="byteBuffer"></param>
public void ReleaseBuffer( byte[] byteBuffer )
{
if ( byteBuffer == null )
throw new ArgumentNullException( "byteBuffer", "BufferPool.ReleaseBuffer(...) - byteBuffer == null error!" );
m_FreeBuffers.Enqueue( byteBuffer );
}
/// <summary>
/// 从存放全局Byte的内存列表中删除自己,被回收内存
/// </summary>
public void Free()
{
s_Pools.Remove( this );
}
/// <summary>
/// 获取内存池的详细信息
/// </summary>
/// <param name="strName"></param>
/// <param name="iFreeCount"></param>
/// <param name="iInitialCapacity"></param>
/// <param name="iCurrentCapacity"></param>
/// <param name="iBufferSize"></param>
/// <param name="iMisses"></param>
public BufferPool.PoolInfo GetPoolInfo()
{
BufferPool.PoolInfo poolInfo = new BufferPool.PoolInfo();
// 该可以不锁定的,因只是读取数据而已
poolInfo.Name = m_BufferName;
poolInfo.Misses = m_Misses;
poolInfo.BufferSize = m_BufferSize;
poolInfo.FreeCount = m_FreeBuffers.Count;
poolInfo.InitialCapacity = m_InitialCapacity;
poolInfo.CurrentCapacity = m_InitialCapacity * ( m_Misses + 1 );
return poolInfo;
}
#endregion
}
FIFOBuffer
/// <summary>
/// Implements FIFO(first in - first out) buffer.
/// </summary>
public class FifoBuffer
{
private object m_pLock = new object();
private byte[] m_pBuffer = null;
private int m_ReadOffset = 0;
private int m_WriteOffset = 0;
/// <summary>
/// Default constructor.
/// </summary>
/// <param name="maxSize">Maximum number of bytes can buffer in FIFO.</param>
/// <exception cref="ArgumentException">Is raised when </exception>
public FifoBuffer(int maxSize)
{
if(maxSize < 1){
throw new ArgumentException("Argument 'maxSize' value must be >= 1.");
}
m_pBuffer = new byte[maxSize];
}
#region method Read
/// <summary>
/// Reads up to specified count of bytes from the FIFO buffer.
/// </summary>
/// <param name="buffer">Buffer where to store data.</param>
/// <param name="offset">Index in the buffer.</param>
/// <param name="count">Maximum number of bytes to read.</param>
/// <returns>Returns number of bytes readed. Returns 0 if no data in the buffer.</returns>
/// <exception cref="ArgumentNullException">Is raised when <b>buffer</b> is null reference.</exception>
/// <exception cref="ArgumentOutOfRangeException">Is raised when any of the arguments has out of allowed range.</exception>
public int Read(byte[] buffer,int offset,int count)
{
if(buffer == null){
throw new ArgumentNullException("buffer");
}
if(offset < 0){
throw new ArgumentOutOfRangeException("offset","Argument 'offset' value must be >= 0.");
}
if(count < 0){
throw new ArgumentOutOfRangeException("count","Argument 'count' value must be >= 0.");
}
if(offset + count > buffer.Length){
throw new ArgumentOutOfRangeException("count","Argument 'count' is bigger than than argument 'buffer' can store.");
}
lock(m_pLock){
int countToRead = Math.Min(count,m_WriteOffset - m_ReadOffset);
if(countToRead > 0){
Array.Copy(m_pBuffer,m_ReadOffset,buffer,offset,countToRead);
m_ReadOffset += countToRead;
}
return countToRead;
}
}
#endregion
#region method Write
/// <summary>
/// Writes specified number of bytes to the FIFO buffer.
/// </summary>
/// <param name="buffer">Data buffer.</param>
/// <param name="offset">Index in the buffer.</param>
/// <param name="count">Number of bytes to wrtite.</param>
/// <param name="ignoreBufferFull">If true, disables excption raising when FIFO full.</param>
/// <exception cref="ArgumentNullException">Is raised when <b>buffer</b> is null reference.</exception>
/// <exception cref="ArgumentOutOfRangeException">Is raised when any of the arguments has out of allowed range.</exception>
/// <exception cref="DataSizeExceededException">Is raised when ignoreBufferFull = false and FIFO buffer has no room to store data.</exception>
public void Write(byte[] buffer,int offset,int count,bool ignoreBufferFull)
{
if(buffer == null){
throw new ArgumentNullException("buffer");
}
if(offset < 0){
throw new ArgumentOutOfRangeException("offset","Argument 'offset' value must be >= 0.");
}
if(count < 0 || (count + offset) > buffer.Length){
throw new ArgumentOutOfRangeException("count");
}
lock(m_pLock){
int freeSpace = m_pBuffer.Length - m_WriteOffset;
// We don't have enough room to store data.
if(freeSpace < count){
TrimStart();
// Recalculate free space.
freeSpace = m_pBuffer.Length - m_WriteOffset;
// After trim we can store data.
if(freeSpace >= count){
Array.Copy(buffer,offset,m_pBuffer,m_WriteOffset,count);
m_WriteOffset += count;
}
// We have not enough space.
else{
if(!ignoreBufferFull){
throw new DataSizeExceededException();
}
}
}
// Store data to buffer.
else{
Array.Copy(buffer,offset,m_pBuffer,m_WriteOffset,count);
m_WriteOffset += count;
}
}
}
#endregion
#region method Clear
/// <summary>
/// Clears buffer data.
/// </summary>
public void Clear()
{
lock(m_pLock){
m_ReadOffset = 0;
m_WriteOffset = 0;
}
}
#endregion
#region method TrimStart
/// <summary>
/// Removes unused space from the buffer beginning.
/// </summary>
private void TrimStart()
{
if(m_ReadOffset > 0){
byte[] buffer = new byte[this.Available];
Array.Copy(m_pBuffer,m_ReadOffset,buffer,0,buffer.Length);
Array.Copy(buffer,m_pBuffer,buffer.Length);
m_ReadOffset = 0;
m_WriteOffset = buffer.Length;
}
}
#endregion
#region Properties implementation
/// <summary>
/// Gets maximum number of bytes can buffer in FIFO.
/// </summary>
public int MaxSize
{
get{ return m_pBuffer.Length; }
}
/// <summary>
/// Gets number of bytes avialable in FIFO.
/// </summary>
public int Available
{
get{ return m_WriteOffset - m_ReadOffset; }
}
#endregion
}