Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

307 lines
7.6 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: Circular Buffer
  4. //
  5. //=============================================================================//
  6. #include "tier0/dbg.h"
  7. #include "tier1/mempool.h"
  8. #include "circularbuffer.h"
  9. // memdbgon must be the last include file in a .cpp file!!!
  10. #include "tier0/memdbgon.h"
  11. CCircularBuffer::CCircularBuffer()
  12. {
  13. SetSize( 0 );
  14. }
  15. CCircularBuffer::CCircularBuffer(int size)
  16. {
  17. SetSize(size);
  18. }
  19. //------------------ Copyright (c) 1999 Valve, LLC. ----------------------------
  20. //Purpose : Sets the maximum size for a circular buffer. This does not do any
  21. // memory allocation, it simply informs the buffer of its size.
  22. //Author : DSpeyrer
  23. //------------------------------------------------------------------------------
  24. void CCircularBuffer::SetSize(int size)
  25. {
  26. Assert( this );
  27. m_nSize = size;
  28. m_nRead = 0;
  29. m_nWrite = 0;
  30. m_nCount = 0;
  31. }
  32. //------------------ Copyright (c) 1999 Valve, LLC. ----------------------------
  33. //Purpose : Empties a circular buffer.
  34. //Author : DSpeyrer
  35. //------------------------------------------------------------------------------
  36. void CCircularBuffer::Flush()
  37. {
  38. AssertValid();
  39. m_nRead = 0;
  40. m_nWrite = 0;
  41. m_nCount = 0;
  42. }
  43. //------------------ Copyright (c) 1999 Valve, LLC. ----------------------------
  44. //Purpose : Returns the available space in a circular buffer.
  45. //Author : DSpeyrer
  46. //------------------------------------------------------------------------------
  47. int CCircularBuffer::GetWriteAvailable()
  48. {
  49. AssertValid();
  50. return(m_nSize - m_nCount);
  51. }
  52. //------------------ Copyright (c) 1999 Valve, LLC. ----------------------------
  53. //Purpose : Returns the size of a circular buffer.
  54. //Author : DSpeyrer
  55. //------------------------------------------------------------------------------
  56. int CCircularBuffer::GetSize()
  57. {
  58. AssertValid();
  59. return(m_nSize);
  60. }
  61. //------------------ Copyright (c) 1999 Valve, LLC. ----------------------------
  62. //Purpose : Returns the number of bytes in a circular buffer.
  63. //Author : DSpeyrer
  64. //------------------------------------------------------------------------------
  65. int CCircularBuffer::GetReadAvailable()
  66. {
  67. AssertValid();
  68. return(m_nCount);
  69. }
  70. //------------------ Copyright (c) 1999 Valve, LLC. ----------------------------
  71. //Purpose : Reads a specified number of bytes from a circular buffer without
  72. // consuming them. They will still be available for future calls to
  73. // Read or Peek.
  74. //Input : pchDest - destination buffer.
  75. // m_nCount - number of bytes to place in destination buffer.
  76. //Output : Returns the number of bytes placed in the destination buffer.
  77. //Author : DSpeyrer
  78. //------------------------------------------------------------------------------
  79. int CCircularBuffer::Peek(char *pchDest, int nCount)
  80. {
  81. // If no data available, just return.
  82. if(m_nCount == 0)
  83. {
  84. return(0);
  85. }
  86. //
  87. // Requested amount should not exceed the available amount.
  88. //
  89. nCount = MIN(m_nCount, nCount);
  90. //
  91. // Copy as many of the requested bytes as possible.
  92. // If buffer wrap occurs split the data into two chunks.
  93. //
  94. if (m_nRead + nCount > m_nSize)
  95. {
  96. int nCount1 = m_nSize - m_nRead;
  97. memcpy(pchDest, &m_chData[m_nRead], nCount1);
  98. pchDest += nCount1;
  99. int nCount2 = nCount - nCount1;
  100. memcpy(pchDest, m_chData, nCount2);
  101. }
  102. // Otherwise copy it in one go.
  103. else
  104. {
  105. memcpy(pchDest, &m_chData[m_nRead], nCount);
  106. }
  107. AssertValid();
  108. return nCount;
  109. }
  110. //------------------ Copyright (c) 1999 Valve, LLC. ----------------------------
  111. //Purpose : Advances the read index, consuming a specified number of bytes from
  112. // the circular buffer.
  113. //Input : m_nCount - number of bytes to consume.
  114. //Output : Returns the actual number of bytes consumed.
  115. //Author : DSpeyrer
  116. //------------------------------------------------------------------------------
  117. int CCircularBuffer::Advance(int nCount)
  118. {
  119. // If no data available, just return.
  120. if (m_nCount == 0)
  121. {
  122. return(0);
  123. }
  124. //
  125. // Requested amount should not exceed the available amount.
  126. //
  127. nCount = MIN(m_nCount, nCount);
  128. //
  129. // Advance the read pointer, checking for buffer wrap.
  130. //
  131. m_nRead = (m_nRead + nCount) % m_nSize;
  132. m_nCount -= nCount;
  133. //
  134. // If we have emptied the buffer, reset the read and write indices
  135. // to minimize buffer wrap.
  136. //
  137. if (m_nCount == 0)
  138. {
  139. m_nRead = 0;
  140. m_nWrite = 0;
  141. }
  142. AssertValid();
  143. return nCount;
  144. }
  145. //------------------ Copyright (c) 1999 Valve, LLC. ----------------------------
  146. //Purpose : Reads a specified number of bytes from a circular buffer. The bytes
  147. // will be consumed by the read process.
  148. //Input : pchDest - destination buffer.
  149. // m_nCount - number of bytes to place in destination buffer.
  150. //Output : Returns the number of bytes placed in the destination buffer.
  151. //Author : DSpeyrer
  152. //------------------------------------------------------------------------------
  153. int CCircularBuffer::Read(void *pchDestIn, int nCount)
  154. {
  155. int nPeeked;
  156. int m_nRead;
  157. char *pchDest = (char*)pchDestIn;
  158. nPeeked = Peek(pchDest, nCount);
  159. if (nPeeked != 0)
  160. {
  161. m_nRead = Advance(nPeeked);
  162. Assert(m_nRead == nPeeked);
  163. }
  164. else
  165. {
  166. m_nRead = 0;
  167. }
  168. AssertValid();
  169. return(m_nRead);
  170. }
  171. //------------------ Copyright (c) 1999 Valve, LLC. ----------------------------
  172. //Purpose : Writes a specified number of bytes to the buffer.
  173. //Input : pm_chData - buffer containing bytes to bw written.
  174. // m_nCount - the number of bytes to write.
  175. //Output : Returns the number of bytes written. If there wa insufficient space
  176. // to write all requested bytes, the value returned will be less than
  177. // the requested amount.
  178. //Author : DSpeyrer
  179. //------------------------------------------------------------------------------
  180. int CCircularBuffer::Write(void *pData, int nBytesRequested)
  181. {
  182. // Write all the data.
  183. int nBytesToWrite = nBytesRequested;
  184. char *pDataToWrite = (char*)pData;
  185. while(nBytesToWrite)
  186. {
  187. int from = m_nWrite;
  188. int to = m_nWrite + nBytesToWrite;
  189. if(to >= m_nSize)
  190. {
  191. to = m_nSize;
  192. }
  193. memcpy(&m_chData[from], pDataToWrite, to - from);
  194. pDataToWrite += to - from;
  195. m_nWrite = to % m_nSize;
  196. nBytesToWrite -= to - from;
  197. }
  198. // Did it cross the read pointer? Then slide the read pointer up.
  199. // This way, we will discard the old data.
  200. if(nBytesRequested > (m_nSize - m_nCount))
  201. {
  202. m_nCount = m_nSize;
  203. m_nRead = m_nWrite;
  204. }
  205. else
  206. {
  207. m_nCount += nBytesRequested;
  208. }
  209. AssertValid();
  210. return nBytesRequested;
  211. }
  212. CFixedBudgetMemoryPool<ALIGN_VALUE(sizeof( CCircularBuffer ) + 8820 - 1, TSLIST_NODE_ALIGNMENT ), 24> g_SmallBuffers;
  213. CFixedBudgetMemoryPool<ALIGN_VALUE(sizeof( CCircularBuffer ) + 17640 - 1, TSLIST_NODE_ALIGNMENT ), 44> g_MediumBuffers;
  214. CFixedBudgetMemoryPool<ALIGN_VALUE(sizeof( CCircularBuffer ) + 35280 - 1, TSLIST_NODE_ALIGNMENT ), 16> g_LargeBuffers;
  215. CCircularBuffer *AllocateCircularBuffer( int nSize )
  216. {
  217. CCircularBuffer *pCCircularBuffer;
  218. if ( nSize <= 8820 )
  219. {
  220. pCCircularBuffer = (CCircularBuffer *)g_SmallBuffers.Alloc();
  221. }
  222. else if ( nSize <= 17640 )
  223. {
  224. pCCircularBuffer = (CCircularBuffer *)g_MediumBuffers.Alloc();
  225. }
  226. else if ( nSize <= 35280 )
  227. {
  228. pCCircularBuffer = (CCircularBuffer *)g_LargeBuffers.Alloc();
  229. }
  230. else
  231. {
  232. pCCircularBuffer = (CCircularBuffer *)malloc( sizeof( CCircularBuffer ) + nSize - 1 );
  233. }
  234. pCCircularBuffer->SetSize( nSize );
  235. return pCCircularBuffer;
  236. }
  237. void FreeCircularBuffer( CCircularBuffer *pCircularBuffer )
  238. {
  239. int nSize = pCircularBuffer->GetSize();
  240. if ( nSize <= 8820 )
  241. {
  242. g_SmallBuffers.Free( pCircularBuffer );
  243. }
  244. else if ( nSize <= 17640 )
  245. {
  246. g_MediumBuffers.Free( pCircularBuffer );
  247. }
  248. else if ( nSize <= 35280 )
  249. {
  250. g_LargeBuffers.Free( pCircularBuffer );
  251. }
  252. else
  253. {
  254. free( pCircularBuffer );
  255. }
  256. }