BufferPool.cpp 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  1. /*
  2. * Copyright: JessMA Open Source (ldcsaa@gmail.com)
  3. *
  4. * Author : Bruce Liang
  5. * Website : https://github.com/ldcsaa
  6. * Project : https://github.com/ldcsaa/HP-Socket
  7. * Blog : http://www.cnblogs.com/ldcsaa
  8. * Wiki : http://www.oschina.net/p/hp-socket
  9. * QQ Group : 44636872, 75375912
  10. *
  11. * Licensed under the Apache License, Version 2.0 (the "License");
  12. * you may not use this file except in compliance with the License.
  13. * You may obtain a copy of the License at
  14. *
  15. * http://www.apache.org/licenses/LICENSE-2.0
  16. *
  17. * Unless required by applicable law or agreed to in writing, software
  18. * distributed under the License is distributed on an "AS IS" BASIS,
  19. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  20. * See the License for the specific language governing permissions and
  21. * limitations under the License.
  22. */
  23. #include "BufferPool.h"
  24. #include "FuncHelper.h"
  25. const DWORD TItem::DEFAULT_ITEM_CAPACITY = DEFAULT_BUFFER_CACHE_CAPACITY;
  26. const DWORD CBufferPool::DEFAULT_MAX_CACHE_SIZE = 0;
  27. const DWORD CBufferPool::DEFAULT_ITEM_CAPACITY = CItemPool::DEFAULT_ITEM_CAPACITY;
  28. const DWORD CBufferPool::DEFAULT_ITEM_POOL_SIZE = CItemPool::DEFAULT_POOL_SIZE;
  29. const DWORD CBufferPool::DEFAULT_ITEM_POOL_HOLD = CItemPool::DEFAULT_POOL_HOLD;
  30. const DWORD CBufferPool::DEFAULT_BUFFER_LOCK_TIME = DEFAULT_OBJECT_CACHE_LOCK_TIME;
  31. const DWORD CBufferPool::DEFAULT_BUFFER_POOL_SIZE = DEFAULT_OBJECT_CACHE_POOL_SIZE;
  32. const DWORD CBufferPool::DEFAULT_BUFFER_POOL_HOLD = DEFAULT_OBJECT_CACHE_POOL_HOLD;
  33. int TItem::Cat(const BYTE* pData, int length)
  34. {
  35. ASSERT(pData != nullptr && length >= 0);
  36. int cat = MIN(Remain(), length);
  37. if(cat > 0)
  38. {
  39. memcpy(end, pData, cat);
  40. end += cat;
  41. }
  42. return cat;
  43. }
  44. int TItem::Cat(const TItem& other)
  45. {
  46. ASSERT(this != &other);
  47. return Cat(other.Ptr(), other.Size());
  48. }
  49. int TItem::Fetch(BYTE* pData, int length)
  50. {
  51. ASSERT(pData != nullptr && length > 0);
  52. int fetch = MIN(Size(), length);
  53. memcpy(pData, begin, fetch);
  54. begin += fetch;
  55. return fetch;
  56. }
  57. int TItem::Peek(BYTE* pData, int length)
  58. {
  59. ASSERT(pData != nullptr && length > 0);
  60. int peek = MIN(Size(), length);
  61. memcpy(pData, begin, peek);
  62. return peek;
  63. }
  64. int TItem::Increase(int length)
  65. {
  66. ASSERT(length >= 0);
  67. int increase = MIN(Remain(), length);
  68. end += increase;
  69. return increase;
  70. }
  71. int TItem::Reduce(int length)
  72. {
  73. ASSERT(length >= 0);
  74. int reduce = MIN(Size(), length);
  75. begin += reduce;
  76. return reduce;
  77. }
  78. void TItem::Reset(int first, int last)
  79. {
  80. ASSERT(first >= -1 && first <= capacity);
  81. ASSERT(last >= -1 && last <= capacity);
  82. if(first >= 0) begin = head + MIN(first, capacity);
  83. if(last >= 0) end = head + MIN(last, capacity);
  84. }
  85. TBuffer* TBuffer::Construct(CBufferPool& pool, ULONG_PTR dwID)
  86. {
  87. ASSERT(dwID != 0);
  88. CPrivateHeap& heap = pool.GetPrivateHeap();
  89. TBuffer* pBuffer = (TBuffer*)heap.Alloc(sizeof(TBuffer));
  90. return ::ConstructObject(pBuffer, heap, pool.GetItemPool(), dwID);
  91. }
  92. void TBuffer::Destruct(TBuffer* pBuffer)
  93. {
  94. ASSERT(pBuffer != nullptr);
  95. CPrivateHeap& heap = pBuffer->heap;
  96. ::DestructObject(pBuffer);
  97. heap.Free(pBuffer);
  98. }
  99. void TBuffer::Reset()
  100. {
  101. id = 0;
  102. length = 0;
  103. freeTime = ::TimeGetTime();
  104. }
  105. int TBuffer::Cat(const BYTE* pData, int len)
  106. {
  107. items.Cat(pData, len);
  108. return IncreaseLength(len);
  109. }
  110. int TBuffer::Cat(const TItem* pItem)
  111. {
  112. items.Cat(pItem);
  113. return IncreaseLength(pItem->Size());
  114. }
  115. int TBuffer::Cat(const TItemList& other)
  116. {
  117. ASSERT(&items != &other);
  118. for(TItem* pItem = other.Front(); pItem != nullptr; pItem = pItem->next)
  119. Cat(pItem);
  120. return length;
  121. }
  122. int TBuffer::Fetch(BYTE* pData, int len)
  123. {
  124. int fetch = items.Fetch(pData, len);
  125. DecreaseLength(fetch);
  126. return fetch;
  127. }
  128. int TBuffer::Peek(BYTE* pData, int len)
  129. {
  130. return items.Peek(pData, len);
  131. }
  132. int TBuffer::Reduce(int len)
  133. {
  134. int reduce = items.Reduce(len);
  135. DecreaseLength(reduce);
  136. return reduce;
  137. }
  138. void CBufferPool::PutFreeBuffer(ULONG_PTR dwID)
  139. {
  140. ASSERT(dwID != 0);
  141. TBuffer* pBuffer = FindCacheBuffer(dwID);
  142. if(pBuffer != nullptr)
  143. PutFreeBuffer(pBuffer);
  144. }
  145. void CBufferPool::PutFreeBuffer(TBuffer* pBuffer)
  146. {
  147. ASSERT(pBuffer != nullptr);
  148. if(!pBuffer->IsValid())
  149. return;
  150. m_bfCache.RemoveEx(pBuffer->ID());
  151. BOOL bOK = FALSE;
  152. {
  153. CCriSecLock locallock(pBuffer->cs);
  154. if(pBuffer->IsValid())
  155. {
  156. pBuffer->Reset();
  157. bOK = TRUE;
  158. }
  159. }
  160. if(bOK)
  161. {
  162. m_itPool.PutFreeItem(pBuffer->items);
  163. #ifndef USE_EXTERNAL_GC
  164. ReleaseGCBuffer();
  165. #endif
  166. if(!m_lsFreeBuffer.TryPut(pBuffer))
  167. m_lsGCBuffer.PushBack(pBuffer);
  168. }
  169. }
  170. void CBufferPool::ReleaseGCBuffer(BOOL bForce)
  171. {
  172. ::ReleaseGCObj(m_lsGCBuffer, m_dwBufferLockTime, bForce);
  173. }
  174. TBuffer* CBufferPool::PutCacheBuffer(ULONG_PTR dwID)
  175. {
  176. ASSERT(dwID != 0);
  177. TBuffer* pBuffer = PickFreeBuffer(dwID);
  178. m_bfCache.SetEx(dwID, pBuffer);
  179. return pBuffer;
  180. }
  181. TBuffer* CBufferPool::PickFreeBuffer(ULONG_PTR dwID)
  182. {
  183. ASSERT( dwID != 0);
  184. DWORD dwIndex;
  185. TBuffer* pBuffer = nullptr;
  186. if(m_lsFreeBuffer.TryLock(&pBuffer, dwIndex))
  187. {
  188. if(::GetTimeGap32(pBuffer->freeTime) >= m_dwBufferLockTime)
  189. VERIFY(m_lsFreeBuffer.ReleaseLock(nullptr, dwIndex));
  190. else
  191. {
  192. VERIFY(m_lsFreeBuffer.ReleaseLock(pBuffer, dwIndex));
  193. pBuffer = nullptr;
  194. }
  195. }
  196. if(pBuffer) pBuffer->id = dwID;
  197. else pBuffer = TBuffer::Construct(*this, dwID);
  198. ASSERT(pBuffer);
  199. return pBuffer;
  200. }
  201. TBuffer* CBufferPool::FindCacheBuffer(ULONG_PTR dwID)
  202. {
  203. ASSERT(dwID != 0);
  204. TBuffer* pBuffer = nullptr;
  205. if(m_bfCache.GetEx(dwID, &pBuffer) != TBufferCache::GR_VALID)
  206. pBuffer = nullptr;
  207. return pBuffer;
  208. }
  209. void CBufferPool::Prepare()
  210. {
  211. m_itPool.Prepare();
  212. m_bfCache.Reset(m_dwMaxCacheSize);
  213. m_lsFreeBuffer.Reset(m_dwBufferPoolSize);
  214. }
  215. void CBufferPool::Clear()
  216. {
  217. TBufferCache::IndexSet& indexes = m_bfCache.Indexes();
  218. for(auto it = indexes.begin(), end = indexes.end(); it != end; ++it)
  219. {
  220. TBuffer* pBuffer = FindCacheBuffer(*it);
  221. if(pBuffer) TBuffer::Destruct(pBuffer);
  222. }
  223. m_bfCache.Reset();
  224. m_lsFreeBuffer.Clear();
  225. ReleaseGCBuffer(TRUE);
  226. VERIFY(m_lsGCBuffer.IsEmpty());
  227. m_itPool.Clear();
  228. m_heap.Reset();
  229. }