using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Sockets;
namespace SuperSocket.Common
{
///
/// This class creates a single large buffer which can be divided up and assigned to SocketAsyncEventArgs objects for use
/// with each socket I/O operation. This enables bufffers to be easily reused and gaurds against fragmenting heap memory.
///
/// The operations exposed on the BufferManager class are not thread safe.
///
public class BufferManager
{
int m_numBytes; // the total number of bytes controlled by the buffer pool
byte[] m_buffer; // the underlying byte array maintained by the Buffer Manager
Stack m_freeIndexPool; //
int m_currentIndex;
int m_bufferSize;
///
/// Initializes a new instance of the class.
///
/// The total bytes.
/// Size of the buffer.
public BufferManager(int totalBytes, int bufferSize)
{
m_numBytes = totalBytes;
m_currentIndex = 0;
m_bufferSize = bufferSize;
m_freeIndexPool = new Stack();
}
///
/// Allocates buffer space used by the buffer pool
///
public void InitBuffer()
{
// create one big large buffer and divide that out to each SocketAsyncEventArg object
m_buffer = new byte[m_numBytes];
}
///
/// Assigns a buffer from the buffer pool to the specified SocketAsyncEventArgs object
///
/// true if the buffer was successfully set, else false
public bool SetBuffer(SocketAsyncEventArgs args)
{
if (m_freeIndexPool.Count > 0)
{
args.SetBuffer(m_buffer, m_freeIndexPool.Pop(), m_bufferSize);
}
else
{
if ((m_numBytes - m_bufferSize) < m_currentIndex)
{
return false;
}
args.SetBuffer(m_buffer, m_currentIndex, m_bufferSize);
m_currentIndex += m_bufferSize;
}
return true;
}
///
/// Removes the buffer from a SocketAsyncEventArg object. This frees the buffer back to the
/// buffer pool
///
public void FreeBuffer(SocketAsyncEventArgs args)
{
m_freeIndexPool.Push(args.Offset);
args.SetBuffer(null, 0, 0);
}
}
}