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); } } }