123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437 |
- /*
- * Copyright: JessMA Open Source (ldcsaa@gmail.com)
- *
- * Version : 2.3.15
- * Author : Bruce Liang
- * Website : http://www.jessma.org
- * Project : https://github.com/ldcsaa
- * Blog : http://www.cnblogs.com/ldcsaa
- * Wiki : http://www.oschina.net/p/hp-socket
- * QQ Group : 75375912
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
- /******************************************************************************
- Module: BufferPool.cpp
- Notices: Copyright (c) 2013 Bruce Liang
- Purpose: ¼òµ¥Äڴ滺³å³Ø
- Desc:
- ******************************************************************************/
- #include "stdafx.h"
- #include "bufferpool.h"
- #include "SysHelper.h"
- #include "WaitFor.h"
- const DWORD TItem::DEFAULT_ITEM_CAPACITY = ::SysGetPageSize();
- const DWORD CBufferPool::DEFAULT_MAX_CACHE_SIZE = 0;
- const DWORD CBufferPool::DEFAULT_ITEM_CAPACITY = CItemPool::DEFAULT_ITEM_CAPACITY;
- const DWORD CBufferPool::DEFAULT_ITEM_POOL_SIZE = CItemPool::DEFAULT_POOL_SIZE;
- const DWORD CBufferPool::DEFAULT_ITEM_POOL_HOLD = CItemPool::DEFAULT_POOL_HOLD;
- const DWORD CBufferPool::DEFAULT_BUFFER_LOCK_TIME = 10 * 1000;
- const DWORD CBufferPool::DEFAULT_BUFFER_POOL_SIZE = 150;
- const DWORD CBufferPool::DEFAULT_BUFFER_POOL_HOLD = 600;
- TItem* TItem::Construct(CPrivateHeap& heap, int capacity, BYTE* pData, int length)
- {
- ASSERT(capacity > 0);
- int item_size = sizeof(TItem);
- TItem* pItem = (TItem*)heap.Alloc(item_size + capacity);
- pItem->head = (BYTE*)pItem + item_size;
- pItem->TItem::TItem(heap, capacity, pData, length);
- return pItem;
- }
- void TItem::Destruct(TItem* pItem)
- {
- ASSERT(pItem != nullptr);
- CPrivateHeap& heap = pItem->heap;
- pItem->TItem::~TItem();
- heap.Free(pItem);
- }
- inline int TItem::Cat(const BYTE* pData, int length)
- {
- ASSERT(pData != nullptr && length > 0);
- int cat = min(Remain(), length);
- if(cat > 0)
- {
- memcpy(end, pData, cat);
- end += cat;
- }
- return cat;
- }
- inline int TItem::Cat(const TItem& other)
- {
- ASSERT(this != &other);
- return Cat(other.Ptr(), other.Size());
- }
- inline int TItem::Fetch(BYTE* pData, int length)
- {
- ASSERT(pData != nullptr && length > 0);
- int fetch = min(Size(), length);
- memcpy(pData, begin, fetch);
- begin += fetch;
- return fetch;
- }
- inline int TItem::Peek(BYTE* pData, int length)
- {
- ASSERT(pData != nullptr && length > 0);
- int peek = min(Size(), length);
- memcpy(pData, begin, peek);
- return peek;
- }
- inline int TItem::Reduce(int length)
- {
- ASSERT(length > 0);
- int reduce = min(Size(), length);
- begin += reduce;
- return reduce;
- }
- inline void TItem::Reset(int first, int last)
- {
- ASSERT(first >= -1 && first <= capacity);
- ASSERT(last >= -1 && last <= capacity);
- if(first >= 0) begin = head + min(first, capacity);
- if(last >= 0) end = head + min(last, capacity);
- }
- int TItemList::Cat(const BYTE* pData, int length)
- {
- int remain = length;
- while(remain > 0)
- {
- TItem* pItem = Back();
- if(pItem == nullptr || pItem->IsFull())
- pItem = PushBack(itPool.PickFreeItem());
- int cat = pItem->Cat(pData, remain);
- pData += cat;
- remain -= cat;
- }
- return length;
- }
- int TItemList::Cat(const TItem* pItem)
- {
- return Cat(pItem->Ptr(), pItem->Size());
- }
- int TItemList::Cat(const TItemList& other)
- {
- ASSERT(this != &other);
- int length = 0;
- for(TItem* pItem = other.Front(); pItem != nullptr; pItem = pItem->next)
- length += Cat(pItem);
- return length;
- }
- int TItemList::Fetch(BYTE* pData, int length)
- {
- int remain = length;
- while(remain > 0 && Size() > 0)
- {
- TItem* pItem = Front();
- int fetch = pItem->Fetch(pData, remain);
- pData += fetch;
- remain -= fetch;
- if(pItem->IsEmpty())
- itPool.PutFreeItem(PopFront());
- }
- return length - remain;
- }
- int TItemList::Peek(BYTE* pData, int length)
- {
- int remain = length;
- TItem* pItem = Front();
- while(remain > 0 && pItem != nullptr)
- {
- int peek = pItem->Peek(pData, remain);
- pData += peek;
- remain -= peek;
- pItem = pItem->next;
- }
- return length - remain;
- }
- int TItemList::Reduce(int length)
- {
- int remain = length;
- while(remain > 0 && Size() > 0)
- {
- TItem* pItem = Front();
- remain -= pItem->Reduce(remain);
- if(pItem->IsEmpty())
- itPool.PutFreeItem(PopFront());
- }
- return length - remain;
- }
- void TItemList::Release()
- {
- itPool.PutFreeItem(*this);
- }
- TBuffer* TBuffer::Construct(CBufferPool& pool, ULONG_PTR dwID)
- {
- ASSERT(dwID != 0);
- CPrivateHeap& heap = pool.GetPrivateHeap();
- TBuffer* pBuffer = (TBuffer*)heap.Alloc(sizeof(TBuffer));
- pBuffer->TBuffer::TBuffer(heap, pool.GetItemPool(), dwID);
- return pBuffer;
- }
- void TBuffer::Destruct(TBuffer* pBuffer)
- {
- ASSERT(pBuffer != nullptr);
- CPrivateHeap& heap = pBuffer->heap;
- pBuffer->TBuffer::~TBuffer();
- heap.Free(pBuffer);
- }
- inline void TBuffer::Reset()
- {
- id = 0;
- length = 0;
- freeTime = ::TimeGetTime();
- }
- int TBuffer::Cat(const BYTE* pData, int len)
- {
- items.Cat(pData, len);
- return IncreaseLength(len);
- }
- int TBuffer::Cat(const TItem* pItem)
- {
- items.Cat(pItem);
- return IncreaseLength(pItem->Size());
- }
- int TBuffer::Cat(const TItemList& other)
- {
- ASSERT(&items != &other);
- for(TItem* pItem = other.Front(); pItem != nullptr; pItem = pItem->next)
- Cat(pItem);
- return length;
- }
- int TBuffer::Fetch(BYTE* pData, int len)
- {
- int fetch = items.Fetch(pData, len);
- DecreaseLength(fetch);
- return fetch;
- }
- int TBuffer::Peek(BYTE* pData, int len)
- {
- return items.Peek(pData, len);
- }
- int TBuffer::Reduce(int len)
- {
- int reduce = items.Reduce(len);
- DecreaseLength(reduce);
- return reduce;
- }
- void CBufferPool::PutFreeBuffer(ULONG_PTR dwID)
- {
- ASSERT(dwID != 0);
- TBuffer* pBuffer = FindCacheBuffer(dwID);
- if(pBuffer != nullptr)
- PutFreeBuffer(pBuffer);
- }
- void CBufferPool::PutFreeBuffer(TBuffer* pBuffer)
- {
- ASSERT(pBuffer != nullptr);
- if(!pBuffer->IsValid())
- return;
- m_bfCache.Remove(pBuffer->ID());
- BOOL bOK = FALSE;
- {
- CCriSecLock locallock(pBuffer->cs);
- if(pBuffer->IsValid())
- {
- pBuffer->Reset();
- bOK = TRUE;
- }
- }
- if(bOK)
- {
- m_itPool.PutFreeItem(pBuffer->items);
- if(!m_lsFreeBuffer.TryPut(pBuffer))
- {
- m_lsGCBuffer.PushBack(pBuffer);
- if(m_lsGCBuffer.Size() > m_dwBufferPoolSize)
- ReleaseGCBuffer();
- }
- }
- }
- void CBufferPool::ReleaseGCBuffer(BOOL bForce)
- {
- TBuffer* pBuffer = nullptr;
- DWORD now = ::TimeGetTime();
- while(m_lsGCBuffer.PopFront(&pBuffer))
- {
- if(bForce || (int)(now - pBuffer->freeTime) >= (int)m_dwBufferLockTime)
- TBuffer::Destruct(pBuffer);
- else
- {
- m_lsGCBuffer.PushBack(pBuffer);
- break;
- }
- }
- }
- TBuffer* CBufferPool::PutCacheBuffer(ULONG_PTR dwID)
- {
- ASSERT(dwID != 0);
- TBuffer* pBuffer = PickFreeBuffer(dwID);
- m_bfCache.Set(dwID, pBuffer);
- return pBuffer;
- }
- TBuffer* CBufferPool::PickFreeBuffer(ULONG_PTR dwID)
- {
- ASSERT( dwID != 0);
- DWORD dwIndex;
- TBuffer* pBuffer = nullptr;
- if(m_lsFreeBuffer.TryLock(&pBuffer, dwIndex))
- {
- if(::GetTimeGap32(pBuffer->freeTime) >= m_dwBufferLockTime)
- m_lsFreeBuffer.ReleaseLock(nullptr, dwIndex);
- else
- {
- m_lsFreeBuffer.ReleaseLock(pBuffer, dwIndex);
- pBuffer = nullptr;
- }
- }
- if(pBuffer) pBuffer->id = dwID;
- else pBuffer = TBuffer::Construct(*this, dwID);
- ASSERT(pBuffer);
- return pBuffer;
- }
- TBuffer* CBufferPool::FindCacheBuffer(ULONG_PTR dwID)
- {
- ASSERT(dwID != 0);
- TBuffer* pBuffer = nullptr;
- if(!m_bfCache.Get(dwID, &pBuffer))
- pBuffer = nullptr;
- return pBuffer;
- }
- void CBufferPool::Prepare()
- {
- m_itPool.Prepare();
- m_bfCache.Reset(m_dwMaxCacheSize);
- m_lsFreeBuffer.Reset(m_dwBufferPoolHold);
- }
- void CBufferPool::Clear()
- {
- DWORD size = 0;
- unique_ptr<ULONG_PTR[]> ids = m_bfCache.GetAllElementIndexes(size, FALSE);
- for(DWORD i = 0; i < size; i++)
- {
- TBuffer* pBuffer = FindCacheBuffer(ids[i]);
- if(pBuffer) TBuffer::Destruct(pBuffer);
- }
- m_bfCache.Reset();
- TBuffer* pBuffer = nullptr;
- while(m_lsFreeBuffer.TryGet(&pBuffer))
- TBuffer::Destruct(pBuffer);
- VERIFY(m_lsFreeBuffer.IsEmpty());
- m_lsFreeBuffer.Reset();
- ReleaseGCBuffer(TRUE);
- VERIFY(m_lsGCBuffer.IsEmpty());
- m_itPool.Clear();
- m_heap.Reset();
- }
|