Index: src/libchcore/ErrorCodes.h =================================================================== diff -u -r835e0344e9677ff02eb3b539061c48c9f3a616ce -r7b840a1bf9e6079f0b78e0c6be794227490e56af --- src/libchcore/ErrorCodes.h (.../ErrorCodes.h) (revision 835e0344e9677ff02eb3b539061c48c9f3a616ce) +++ src/libchcore/ErrorCodes.h (.../ErrorCodes.h) (revision 7b840a1bf9e6079f0b78e0c6be794227490e56af) @@ -76,6 +76,9 @@ // Task handling errors eErr_MissingTaskSerializationPath = 4000, eErr_UndefinedOperation = 4001, + + // Memory allocation/deallocation + eErr_CannotAllocateMemory = 4500, }; END_CHCORE_NAMESPACE Index: src/libchcore/TDataBuffer.cpp =================================================================== diff -u --- src/libchcore/TDataBuffer.cpp (revision 0) +++ src/libchcore/TDataBuffer.cpp (revision 7b840a1bf9e6079f0b78e0c6be794227490e56af) @@ -0,0 +1,164 @@ +// ============================================================================ +// Copyright (C) 2001-2012 by Jozef Starosczyk +// ixen@copyhandler.com +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU Library General Public License +// (version 2) as published by the Free Software Foundation; +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// ============================================================================ +/// @file TDataBuffer.cpp +/// @date 2012/03/04 +/// @brief Contains class representing buffer for data. +// ============================================================================ +#include "stdafx.h" +#include "TDataBuffer.h" + +BEGIN_CHCORE_NAMESPACE + +namespace +{ + const size_t c_DefaultAllocGranularity = 4096; + const size_t c_DefaultSimpleBufferSize = 65536; + const size_t c_DefaultBlockSize = 1024*1024; + const size_t c_DefaultBufferSize = 1024*1024; + + template T RoundUp(T number, T roundValue) { return ((number + roundValue - 1) & ~(roundValue - 1)); } +} + +/////////////////////////////////////////////////////////////////////////////////// +// class TSimpleDataBuffer + +TSimpleDataBuffer::TSimpleDataBuffer() : + m_pBuffer(NULL), + m_pBufferManager(NULL) +{ +} + +TSimpleDataBuffer::~TSimpleDataBuffer() +{ + ReleaseBuffer(); +} + +LPVOID TSimpleDataBuffer::GetBufferPtr() +{ + return m_pBuffer; +} + +void TSimpleDataBuffer::ReleaseBuffer() +{ + if(m_pBufferManager && m_pBuffer) + m_pBufferManager->ReleaseBuffer(*this); +} + +void TSimpleDataBuffer::Initialize(TDataBufferManager& rBufferManager, LPVOID pBuffer) +{ + ReleaseBuffer(); + m_pBufferManager = &rBufferManager; + m_pBuffer = pBuffer; +} + +/////////////////////////////////////////////////////////////////////////////////// +// class TDataBufferManager + +TDataBufferManager::TDataBufferManager() : + m_stChunkSize(0), + m_stAllocBlockSize(0), + m_stCountOfSimpleBuffers(0) +{ +} + +TDataBufferManager::~TDataBufferManager() +{ + FreeBuffers(); +} + +void TDataBufferManager::Initialize(size_t stBufferSize, size_t stBlockSize, size_t stSimpleBufferSize) +{ + FreeBuffers(); + + if(stSimpleBufferSize == 0) + stSimpleBufferSize = c_DefaultSimpleBufferSize; + if(stBlockSize == 0) + stBlockSize = c_DefaultBlockSize; + if(stBufferSize == 0) + stBufferSize = c_DefaultBufferSize; + + m_stCountOfSimpleBuffers = 0; + m_stChunkSize = RoundUp(stSimpleBufferSize, c_DefaultAllocGranularity); + m_stAllocBlockSize = RoundUp(stBlockSize, m_stChunkSize); + + size_t stSimpleBuffersPerBlock = m_stAllocBlockSize / m_stChunkSize; + size_t stBlockCount = RoundUp(stBufferSize, m_stAllocBlockSize) / m_stAllocBlockSize; + + for(size_t stIndex = 0; stIndex < stBlockCount; ++stIndex) + { + // allocate + LPVOID pBuffer = VirtualAlloc(NULL, m_stAllocBlockSize, MEM_COMMIT, PAGE_READWRITE); + if(!pBuffer) + THROW_CORE_EXCEPTION(eErr_CannotAllocateMemory); + + m_vVirtualAllocBlocks.push_back(pBuffer); + + // and slice + for(size_t stSimpleIndex = 0; stSimpleIndex < stSimpleBuffersPerBlock; ++stSimpleIndex) + { + LPVOID pSimpleBuffer = (BYTE*)pBuffer + stSimpleIndex * m_stChunkSize; + m_listUnusedSimpleBuffers.push_back(pSimpleBuffer); + ++m_stCountOfSimpleBuffers; + } + } +} + +bool TDataBufferManager::HasFreeBuffer() const +{ + return !m_listUnusedSimpleBuffers.empty(); +} + +bool TDataBufferManager::GetFreeBuffer(TSimpleDataBuffer& rSimpleBuffer) +{ + if(!m_listUnusedSimpleBuffers.empty()) + { + LPVOID pBuffer = m_listUnusedSimpleBuffers.front(); + m_listUnusedSimpleBuffers.pop_front(); + rSimpleBuffer.Initialize(*this, pBuffer); + return true; + } + + return false; +} + +void TDataBufferManager::ReleaseBuffer(TSimpleDataBuffer& rSimpleBuffer) +{ + if(rSimpleBuffer.m_pBuffer) + m_listUnusedSimpleBuffers.push_back(rSimpleBuffer.m_pBuffer); +} + +void TDataBufferManager::FreeBuffers() +{ + _ASSERTE(m_listUnusedSimpleBuffers.size() == m_stCountOfSimpleBuffers); + if(m_listUnusedSimpleBuffers.size() != m_stCountOfSimpleBuffers) + THROW_CORE_EXCEPTION(eErr_InternalProblem); + + for(std::vector::iterator iterMem = m_vVirtualAllocBlocks.begin(); iterMem != m_vVirtualAllocBlocks.end(); ++iterMem) + { + VirtualFree(*iterMem, 0, MEM_RELEASE); + } + + m_vVirtualAllocBlocks.clear(); + m_listUnusedSimpleBuffers.clear(); + m_stCountOfSimpleBuffers = 0; + m_stAllocBlockSize = 0; + m_stChunkSize = 0; +} + +END_CHCORE_NAMESPACE Index: src/libchcore/TDataBuffer.h =================================================================== diff -u --- src/libchcore/TDataBuffer.h (revision 0) +++ src/libchcore/TDataBuffer.h (revision 7b840a1bf9e6079f0b78e0c6be794227490e56af) @@ -0,0 +1,83 @@ +// ============================================================================ +// Copyright (C) 2001-2012 by Jozef Starosczyk +// ixen@copyhandler.com +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU Library General Public License +// (version 2) as published by the Free Software Foundation; +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// ============================================================================ +/// @file TDataBuffer.h +/// @date 2012/03/04 +/// @brief Contains class representing buffer for data. +// ============================================================================ +#ifndef __TDATABUFFER_H__ +#define __TDATABUFFER_H__ + +#include "libchcore.h" +#include +#include + +BEGIN_CHCORE_NAMESPACE + +class TDataBufferManager; + +class TSimpleDataBuffer +{ +public: + TSimpleDataBuffer(); + ~TSimpleDataBuffer(); + + LPVOID GetBufferPtr(); + void ReleaseBuffer(); + +private: + TSimpleDataBuffer(const TSimpleDataBuffer&); + TSimpleDataBuffer& operator=(const TSimpleDataBuffer&); + + void Initialize(TDataBufferManager& rBufferManager, LPVOID pBuffer); + +private: + LPVOID m_pBuffer; + TDataBufferManager* m_pBufferManager; + + friend class TDataBufferManager; +}; + +class TDataBufferManager +{ +public: + TDataBufferManager(); + ~TDataBufferManager(); + + void Initialize(size_t stBufferSize, size_t stBlockSize, size_t stSimpleBufferSize); + + bool HasFreeBuffer() const; + bool GetFreeBuffer(TSimpleDataBuffer& rSimpleBuffer); + void ReleaseBuffer(TSimpleDataBuffer& rSimpleBuffer); + +private: + void FreeBuffers(); + +private: + + std::vector m_vVirtualAllocBlocks; + std::list m_listUnusedSimpleBuffers; + + size_t m_stAllocBlockSize; // size of the memory block in m_vVirtualAllocBlocks + size_t m_stChunkSize; // size of the simple buffer (part of the real buffer) + size_t m_stCountOfSimpleBuffers; +}; + +END_CHCORE_NAMESPACE + +#endif Index: src/libchcore/libchcore.vc90.vcproj =================================================================== diff -u -r12a1725bfd04b0f55fd0fda302975fdcd4174943 -r7b840a1bf9e6079f0b78e0c6be794227490e56af --- src/libchcore/libchcore.vc90.vcproj (.../libchcore.vc90.vcproj) (revision 12a1725bfd04b0f55fd0fda302975fdcd4174943) +++ src/libchcore/libchcore.vc90.vcproj (.../libchcore.vc90.vcproj) (revision 7b840a1bf9e6079f0b78e0c6be794227490e56af) @@ -495,6 +495,14 @@ > + + + +