IOBuffer.cpp
上传用户:dzyhzl
上传日期:2019-04-29
资源大小:56270k
文件大小:7k
源码类别:

模拟服务器

开发平台:

C/C++

  1. #include "stdafx.h"
  2. #include "IOBuffer.h"
  3. #include "Exception.h"
  4. #include "Utils.h"
  5. /*
  6.  * namespace OnlineGameLib::Win32
  7.  */
  8. namespace OnlineGameLib {
  9. namespace Win32 {
  10. CIOBuffer::CIOBuffer( Allocator &allocator, size_t size )
  11. :  m_operation( 0 )
  12.       , m_sequenceNumber( 0 )
  13.       , m_allocator( allocator )
  14.       , m_ref( 1 )
  15.       , m_size( size )
  16.       , m_used( 0 )
  17. {
  18. //( ( BYTE * )( ( DWORD )( pMemory + 3 ) & ( ~3 ) ) )
  19. m_buffer_ptr = new BYTE[ size ];
  20. memset( this, 0, sizeof( OVERLAPPED ) );
  21. Empty();
  22. }
  23. CIOBuffer::~CIOBuffer()
  24. {
  25. SAFE_DELETE_ARRAY( m_buffer_ptr );
  26. }
  27. void CIOBuffer::Empty()
  28. {
  29. m_wsabuf.buf = reinterpret_cast< char * >( m_buffer_ptr );
  30. m_wsabuf.len = m_size;
  31. m_used = 0;
  32. }
  33. void *CIOBuffer::operator new( size_t objectSize, size_t /* bufferSize */ )
  34. {
  35. /*
  36.  * ASSERT( sizeof( DWORD ) == 4 );
  37.  *
  38.  * For four bytes aligned base on win32 system
  39.  */
  40. void *pMem = new char[ objectSize ]; // + bufferSize + 4 ];
  41. return pMem;
  42. }
  43. void CIOBuffer::operator delete( void *pObject, size_t /* bufferSize*/ )
  44. {
  45. SAFE_DELETE_ARRAY( pObject );
  46. }
  47. CIOBuffer *CIOBuffer::SplitBuffer( size_t bytesToRemove )
  48. {
  49. CIOBuffer *pNewBuffer = m_allocator.Allocate();
  50. pNewBuffer->AddData( m_buffer_ptr, bytesToRemove );
  51. m_used -= bytesToRemove;
  52. memmove( m_buffer_ptr, m_buffer_ptr + bytesToRemove, m_used );
  53. return pNewBuffer;
  54. }
  55. VOID CIOBuffer::RemoveBuffer( size_t bytesToRemove )
  56. {
  57. if ( m_used < bytesToRemove )
  58. return;
  59. m_used -= bytesToRemove;
  60. memmove( m_buffer_ptr, m_buffer_ptr + bytesToRemove, m_used );
  61. }
  62. CIOBuffer *CIOBuffer::AllocateNewBuffer() const
  63. {
  64. return m_allocator.Allocate();
  65. }
  66. void CIOBuffer::AddData( const char * const pData, size_t dataLength )
  67. {
  68. if (dataLength > m_size - m_used)
  69. {
  70. DEBUG_ONLY( Message( "CIOBuffer::AddData - Not enough space in buffer!" ) );
  71. throw CException( _T("CIOBuffer::AddData"), _T("Not enough space in buffer") );
  72. }
  73. memcpy( m_buffer_ptr + m_used, pData, dataLength );
  74. m_used += dataLength;
  75. }
  76. void CIOBuffer::AddData( const BYTE * const pData, size_t dataLength )
  77. {
  78. AddData( reinterpret_cast< const char * >( pData ), dataLength );
  79. }
  80. void CIOBuffer::AddData( BYTE data )
  81. {
  82. AddData( &data, 1 );
  83. }
  84. void CIOBuffer::Release()
  85. {
  86. if (m_ref == 0)
  87. {
  88. /*
  89.  * Error! double release
  90.  */
  91. throw CException( _T("CIOBuffer::Release()"), _T("m_ref is already zero") );
  92. }
  93. if ( 0 == ::InterlockedDecrement( &m_ref ) )
  94. {
  95. m_sequenceNumber = 0;
  96. m_operation = 0;
  97. m_used = 0;
  98. m_allocator.Release( this );
  99. }
  100. }
  101. /*
  102.  * CIOBuffer::Allocator
  103.  */
  104. CIOBuffer::Allocator::Allocator( size_t bufferSize, size_t maxFreeBuffers )
  105.    :  m_bufferSize( bufferSize ),
  106.       m_maxFreeBuffers( maxFreeBuffers )
  107. {
  108. }
  109. CIOBuffer::Allocator::~Allocator()
  110. {
  111. try
  112. {
  113. Flush();
  114. }
  115. catch(...)
  116. {
  117. TRACE( "CIOBuffer::Allocator::~Allocator exception!" );
  118. }
  119. }
  120. CIOBuffer *CIOBuffer::Allocator::Allocate()
  121. {
  122. CCriticalSection::Owner lock( m_criticalSection );
  123. CIOBuffer *pBuffer = 0;
  124. if ( !m_freeList.Empty() )
  125. {
  126. pBuffer = m_freeList.PopNode();
  127. pBuffer->AddRef();
  128. }
  129. else
  130. {
  131. pBuffer = new( m_bufferSize )CIOBuffer( *this, m_bufferSize );
  132. if ( !pBuffer )
  133. {
  134. throw CException( _T("CIOBuffer::Allocator::Allocate()"), _T("Out of memory") );
  135. }
  136. OnBufferCreated();
  137. }
  138. m_activeList.PushNode( pBuffer );
  139. OnBufferAllocated();
  140. return pBuffer;
  141. }
  142. void CIOBuffer::Allocator::Release( CIOBuffer *pBuffer )
  143. {
  144. if ( !pBuffer )
  145. {
  146. throw CException( _T("CIOBuffer::Allocator::Release()"), _T("pBuffer is null") );
  147. }
  148. CCriticalSection::Owner lock( m_criticalSection );
  149. OnBufferReleased();
  150. /*
  151.  * unlink from the in use list
  152.  */
  153. pBuffer->RemoveFromList();
  154. if ( m_maxFreeBuffers == 0 || m_freeList.Count() < m_maxFreeBuffers )
  155. {
  156. pBuffer->Empty();           
  157. /*
  158.  * add to the free list
  159.  */
  160. m_freeList.PushNode( pBuffer );
  161. }
  162. else
  163. {
  164. DestroyBuffer( pBuffer );
  165. }
  166. }
  167. void CIOBuffer::Allocator::DestroyBuffer( CIOBuffer *pBuffer )
  168. {
  169. SAFE_DELETE( pBuffer );
  170. }
  171. void CIOBuffer::Allocator::Flush()
  172. {
  173. CCriticalSection::Owner lock( m_criticalSection );
  174. while ( !m_activeList.Empty() )
  175. {
  176. OnBufferReleased();
  177. DestroyBuffer( m_activeList.PopNode() );
  178. }
  179. while ( !m_freeList.Empty() )
  180. {
  181. DestroyBuffer( m_freeList.PopNode() );
  182. }
  183. }
  184. /*
  185.  * CIOBuffer::InOrderBufferList
  186.  */
  187. CIOBuffer::InOrderBufferList::InOrderBufferList(
  188. CCriticalSection &criticalSection)
  189. :   m_next(0),
  190. m_criticalSection( criticalSection )
  191. {
  192. }
  193. void CIOBuffer::InOrderBufferList::AddBuffer( CIOBuffer *pBuffer )
  194. {
  195. CCriticalSection::Owner lock( m_criticalSection );
  196. std::pair< BufferSequence::iterator, bool > result = 
  197. m_list.insert( BufferSequence::value_type( pBuffer->GetSequenceNumber(), pBuffer ) );
  198. if ( !result.second )
  199. {
  200. DEBUG_ONLY( Output( _T("UNEXPECTED! element already in map!") ) );
  201. }
  202. }
  203. CIOBuffer *CIOBuffer::InOrderBufferList::ProcessAndGetNext()
  204. {
  205. CCriticalSection::Owner lock( m_criticalSection );
  206. m_next ++;
  207. CIOBuffer *pNext = 0;
  208. BufferSequence::iterator it;
  209. it = m_list.begin();
  210. if ( it != m_list.end() )
  211. {
  212. if ( it->first == m_next )
  213. {
  214. pNext = it->second;
  215. m_list.erase( it );
  216. }
  217. else
  218. {
  219. DEBUG_ONLY( Output( ToString( this ) +
  220. _T(" Got buffer : ") + 
  221. ToString( it->first ) +
  222. _T("Want buffer : ") +
  223. ToString( m_next ) ) );
  224. }
  225. }
  226. return pNext;
  227. }
  228. CIOBuffer *CIOBuffer::InOrderBufferList::GetNext()
  229. {
  230. CCriticalSection::Owner lock( m_criticalSection );
  231. CIOBuffer *pNext = 0;
  232. BufferSequence::iterator it;
  233. it = m_list.begin();
  234. if ( it != m_list.end() )
  235. {
  236. if ( it->first == m_next )
  237. {
  238. pNext = it->second;
  239. m_list.erase(it);
  240. }
  241. else
  242. {
  243. DEBUG_ONLY( Output( ToString( this ) + 
  244. _T(" Got buffer  : ") + 
  245. ToString( it->first ) + 
  246. _T("Want buffer : ") + 
  247. ToString( m_next ) ) );
  248. }
  249. }
  250. return pNext;
  251. }
  252. CIOBuffer *CIOBuffer::InOrderBufferList::GetNext( CIOBuffer *pBuffer )
  253. {
  254. CCriticalSection::Owner lock( m_criticalSection );
  255. if ( m_next == pBuffer->GetSequenceNumber() )
  256. {
  257. return pBuffer;
  258. }
  259. std::pair< BufferSequence::iterator, bool > result = 
  260. m_list.insert( BufferSequence::value_type( pBuffer->GetSequenceNumber(), pBuffer ) );
  261. if ( !result.second )
  262. {
  263. DEBUG_ONLY( Output( _T("UNEXPECTED! element already in map!") ) );
  264. }
  265. CIOBuffer *pNext = 0;
  266. BufferSequence::iterator it;
  267. it = m_list.begin();
  268. if (it != m_list.end()) 
  269. {
  270. if (it->first == m_next)
  271. {
  272. pNext = it->second;
  273. m_list.erase(it);
  274. }
  275. else
  276. {
  277. DEBUG_ONLY( Output( ToString( this ) +
  278. _T(" Got buffer  : ") + 
  279. ToString( it->first ) + 
  280. _T("Want buffer : ") + 
  281. ToString( m_next ) ) );
  282. }
  283. }
  284. return pNext;
  285. }
  286. void CIOBuffer::InOrderBufferList::ProcessBuffer()
  287. {
  288. CCriticalSection::Owner lock( m_criticalSection );
  289. DEBUG_ONLY( Output( ToString( this ) +
  290. _T(" Processed : ") + 
  291. ToString( m_next ) ) );
  292. m_next ++;
  293. }
  294. void CIOBuffer::InOrderBufferList::Reset()
  295. {
  296. m_next = 0;
  297. if ( !m_list.empty() )
  298. {
  299. DEBUG_ONLY( Output( _T("List not empty when reset !") ) );
  300. }
  301. }
  302. } // End of namespace Win32
  303. } // End of namespace OnlineGameLib