Index: src/libchcore/TDataBuffer.cpp =================================================================== diff -u -rb013066ba827b440b2e281bd58e8b16e51a080d7 -r2cc200f4b40dedfdebafab18bf07c733be47da8a --- src/libchcore/TDataBuffer.cpp (.../TDataBuffer.cpp) (revision b013066ba827b440b2e281bd58e8b16e51a080d7) +++ src/libchcore/TDataBuffer.cpp (.../TDataBuffer.cpp) (revision 2cc200f4b40dedfdebafab18bf07c733be47da8a) @@ -22,6 +22,7 @@ // ============================================================================ #include "stdafx.h" #include "TDataBuffer.h" +#include BEGIN_CHCORE_NAMESPACE @@ -83,7 +84,8 @@ setChunks.insert(*iterList); } - return setChunks.size(); + // include chunks already owned + return setChunks.size() + m_setFreeChunks.size(); } bool TVirtualAllocMemoryBlock::IsChunkOwner(LPVOID pChunk) const @@ -149,6 +151,7 @@ } } + /////////////////////////////////////////////////////////////////////////////////// // class TSimpleDataBuffer @@ -207,15 +210,16 @@ TDataBufferManager::TDataBufferManager() : m_stMaxMemory(0), m_stPageSize(0), - m_stBufferSize(0) + m_stBufferSize(0), + m_stAllocBlocksToFree(0) { } TDataBufferManager::~TDataBufferManager() { try { - FreeBuffers(); + FreeAllAllocBlocks(); } catch(...) { @@ -290,7 +294,7 @@ void TDataBufferManager::Initialize(size_t stMaxMemory, size_t stPageSize, size_t stBufferSize) { - FreeBuffers(); + FreeAllAllocBlocks(); // validate input (note that input parameters should already be checked by caller) if(!CheckBufferConfig(stMaxMemory, stPageSize, stBufferSize)) @@ -365,7 +369,7 @@ size_t TDataBufferManager::GetRealAllocatedMemorySize() const { - return m_stPageSize * (m_vAllocBlocksToFree.size() + m_vVirtualAllocBlocks.size()); + return m_stPageSize * m_vVirtualAllocBlocks.size(); } bool TDataBufferManager::HasFreeBuffer() const @@ -378,9 +382,11 @@ if(!IsInitialized()) return 0; + size_t stActivePages = m_vVirtualAllocBlocks.size() - m_stAllocBlocksToFree; + // count of unallocated pages size_t stCurrentMaxPages = m_stMaxMemory / m_stPageSize; - size_t stPagesStillUnallocated = stCurrentMaxPages - m_vVirtualAllocBlocks.size(); + size_t stPagesStillUnallocated = stCurrentMaxPages - stActivePages; return m_listUnusedBuffers.size() + stPagesStillUnallocated * m_stPageSize / m_stBufferSize; } @@ -400,36 +406,35 @@ if(!IsInitialized()) return false; + size_t stActivePages = m_vVirtualAllocBlocks.size() - m_stAllocBlocksToFree; size_t stMaxPages = m_stMaxMemory / m_stPageSize; - return m_vVirtualAllocBlocks.size() < stMaxPages; + return stActivePages < stMaxPages; } bool TDataBufferManager::AllocNewPage() { if(!CanAllocPage()) return false; - if(!m_vAllocBlocksToFree.empty()) + // re-use the old block if possible + if(m_stAllocBlocksToFree != 0) { - // re-use the already disposed-of alloc block - for(std::vector::iterator iterAllocBlock = m_vAllocBlocksToFree.begin(); iterAllocBlock != m_vAllocBlocksToFree.end(); ++iterAllocBlock) + for(MemoryBlocksVector::iterator iterMem = m_vVirtualAllocBlocks.begin(); iterMem != m_vVirtualAllocBlocks.end(); ++iterMem) { - details::TVirtualAllocMemoryBlockPtr spAllocBlock(*iterAllocBlock); - if(spAllocBlock->HasFreeChunks()) + if((*iterMem).second == eBlock_ToFree && (*iterMem).first->HasFreeChunks()) { - m_vVirtualAllocBlocks.push_back(spAllocBlock); - m_vAllocBlocksToFree.erase(iterAllocBlock); + (*iterMem).second = eBlock_Active; + --m_stAllocBlocksToFree; + (*iterMem).first->GetFreeChunks(m_listUnusedBuffers); - spAllocBlock->GetFreeChunks(m_listUnusedBuffers); - return true; } } } // alloc new block if can't re-use the old one details::TVirtualAllocMemoryBlockPtr spAllocBlock(new details::TVirtualAllocMemoryBlock(m_stPageSize, m_stBufferSize)); - m_vVirtualAllocBlocks.push_back(spAllocBlock); + m_vVirtualAllocBlocks.push_back(std::make_pair(spAllocBlock, eBlock_Active)); spAllocBlock->GetFreeChunks(m_listUnusedBuffers); return true; @@ -441,9 +446,11 @@ return; std::vector > vFreeBuffers; - for(std::vector::iterator iterAllocBlock = m_vVirtualAllocBlocks.begin(); iterAllocBlock != m_vVirtualAllocBlocks.end(); ++iterAllocBlock) + for(MemoryBlocksVector::iterator iterAllocBlock = m_vVirtualAllocBlocks.begin(); + iterAllocBlock != m_vVirtualAllocBlocks.end() && (*iterAllocBlock).second == eBlock_Active; + ++iterAllocBlock) { - vFreeBuffers.push_back(std::make_pair(*iterAllocBlock, (*iterAllocBlock)->CountOwnChunks(m_listUnusedBuffers))); + vFreeBuffers.push_back(std::make_pair((*iterAllocBlock).first, (*iterAllocBlock).first->CountOwnChunks(m_listUnusedBuffers))); } // sort by the count of free blocks @@ -455,22 +462,59 @@ for(size_t stIndex = 0; stIndex < stPagesToProcess; ++stIndex) { FreePage(vFreeBuffers[stIndex].first); + m_stMaxMemory -= m_stPageSize; } } // function expects arrays to be sorted -void TDataBufferManager::FreePage(const details::TVirtualAllocMemoryBlockPtr& spAllocBlock) +bool TDataBufferManager::FreePage(const details::TVirtualAllocMemoryBlockPtr& spAllocBlock) { + // locate the entry + MemoryBlocksVector::iterator iterBlock = std::find_if(m_vVirtualAllocBlocks.begin(), m_vVirtualAllocBlocks.end(), + boost::bind(&std::pair::first, _1) == spAllocBlock); + + if(iterBlock == m_vVirtualAllocBlocks.end()) + THROW_CORE_EXCEPTION(eErr_InvalidArgument); + + // remove the entries from unused buffers spAllocBlock->ReleaseChunks(m_listUnusedBuffers); + + // if some buffers are still in use - mark the whole block as additional cleaning needed if(!spAllocBlock->AreAllChunksFree()) - m_vAllocBlocksToFree.push_back(spAllocBlock); + { + if((*iterBlock).second == eBlock_Active) + { + (*iterBlock).second = eBlock_ToFree; + ++m_stAllocBlocksToFree; + } + } + else + { + if((*iterBlock).second == eBlock_ToFree) + --m_stAllocBlocksToFree; + m_vVirtualAllocBlocks.erase(iterBlock); + return true; // erased + } - std::vector::iterator iterAllocBlock = std::find(m_vVirtualAllocBlocks.begin(), m_vVirtualAllocBlocks.end(), spAllocBlock); - if(iterAllocBlock == m_vVirtualAllocBlocks.end()) - THROW_CORE_EXCEPTION(eErr_InternalProblem); - m_vVirtualAllocBlocks.erase(iterAllocBlock); + return false; // not erased +} - m_stMaxMemory -= m_stPageSize; +void TDataBufferManager::ReclaimPage(const details::TVirtualAllocMemoryBlockPtr& spAllocBlock) +{ + // locate the entry + MemoryBlocksVector::iterator iterBlock = std::find_if(m_vVirtualAllocBlocks.begin(), m_vVirtualAllocBlocks.end(), + boost::bind(&std::pair::first, _1) == spAllocBlock); + + if(iterBlock == m_vVirtualAllocBlocks.end()) + THROW_CORE_EXCEPTION(eErr_InvalidArgument); + + // remove the entries from unused buffers + if((*iterBlock).second == eBlock_ToFree) + { + spAllocBlock->GetFreeChunks(m_listUnusedBuffers); + (*iterBlock).second = eBlock_Active; + --m_stAllocBlocksToFree; + } } bool TDataBufferManager::GetFreeBuffer(TSimpleDataBuffer& rSimpleBuffer) @@ -501,45 +545,82 @@ { if(rSimpleBuffer.m_pBuffer) { - if(!m_vAllocBlocksToFree.empty()) + if(m_stAllocBlocksToFree != 0) { - for(std::vector::iterator iterAllocBlock = m_vAllocBlocksToFree.begin(); iterAllocBlock != m_vAllocBlocksToFree.end(); ++iterAllocBlock) + // return the buffer to the rightful owner in case we're trying to reduce memory footprint + for(MemoryBlocksVector::iterator iterBlock = m_vVirtualAllocBlocks.begin(); iterBlock != m_vVirtualAllocBlocks.end() && (*iterBlock).second == eBlock_ToFree; ++iterBlock) { - const details::TVirtualAllocMemoryBlockPtr& spAllocBlock = (*iterAllocBlock); + const details::TVirtualAllocMemoryBlockPtr& spAllocBlock = (*iterBlock).first; if(spAllocBlock->IsChunkOwner(rSimpleBuffer.m_pBuffer)) { spAllocBlock->ReleaseChunk(rSimpleBuffer.m_pBuffer); if(spAllocBlock->AreAllChunksFree()) { - m_vAllocBlocksToFree.erase(iterAllocBlock); + --m_stAllocBlocksToFree; + m_vVirtualAllocBlocks.erase(iterBlock); } + return; } } + + // at this point we know that the buffer belongs to an active page + // and at the same time we have some pages still to be freed + m_listUnusedBuffers.push_back(rSimpleBuffer.m_pBuffer); + ReorganizePages(); + return; } m_listUnusedBuffers.push_back(rSimpleBuffer.m_pBuffer); } } -void TDataBufferManager::FreeBuffers() +void TDataBufferManager::ReorganizePages() { - for(std::vector::iterator iterAllocBlock = m_vVirtualAllocBlocks.begin(); iterAllocBlock != m_vVirtualAllocBlocks.end(); ++iterAllocBlock) + // prepare sorted pages + std::vector > vFreeBuffers; + for(MemoryBlocksVector::iterator iterAllocBlock = m_vVirtualAllocBlocks.begin(); + iterAllocBlock != m_vVirtualAllocBlocks.end(); + ++iterAllocBlock) { - (*iterAllocBlock)->ReleaseChunks(m_listUnusedBuffers); - _ASSERTE((*iterAllocBlock)->AreAllChunksFree()); // without throwing on this condition, because there might be a situation that + vFreeBuffers.push_back(std::make_pair((*iterAllocBlock).first, (*iterAllocBlock).first->CountOwnChunks(m_listUnusedBuffers))); + } + + // sort by the count of free blocks + std::sort(vFreeBuffers.begin(), vFreeBuffers.end(), + boost::bind(&std::pair::second, _1) > boost::bind(&std::pair::second, _2)); + + // and free pages with the most free blocks inside + size_t stPagesToFree = std::min(m_stAllocBlocksToFree, vFreeBuffers.size()); + + size_t stIndex = 0; + for(; stIndex < stPagesToFree; ++stIndex) + { + FreePage(vFreeBuffers[stIndex].first); + } + + // activate some other pages + size_t stPagesToActivate = std::min(stIndex + m_stAllocBlocksToFree, vFreeBuffers.size()); + for(; stIndex < stPagesToActivate; ++stIndex) + { + ReclaimPage(vFreeBuffers[stIndex].first); + } +} + +void TDataBufferManager::FreeAllAllocBlocks() +{ + for(MemoryBlocksVector::iterator iterAllocBlock = m_vVirtualAllocBlocks.begin(); iterAllocBlock != m_vVirtualAllocBlocks.end(); ++iterAllocBlock) + { + (*iterAllocBlock).first->ReleaseChunks(m_listUnusedBuffers); + _ASSERTE((*iterAllocBlock).first->AreAllChunksFree()); // without throwing on this condition, because there might be a situation that // some hanged thread did not release the buffer } - _ASSERTE(m_vAllocBlocksToFree.empty()); // virtual alloc blocks to free should be empty at this point (because all the - // buffers should be returned to the pool) _ASSERTE(m_listUnusedBuffers.empty()); // and all buffers should be returned to the pool by the caller if(!m_listUnusedBuffers.empty()) THROW_CORE_EXCEPTION(eErr_InternalProblem); m_vVirtualAllocBlocks.clear(); - m_vAllocBlocksToFree.clear(); - //m_listUnusedBuffers.clear(); m_stBufferSize = 0; m_stPageSize = 0; Index: src/libchcore/TDataBuffer.h =================================================================== diff -u -rb013066ba827b440b2e281bd58e8b16e51a080d7 -r2cc200f4b40dedfdebafab18bf07c733be47da8a --- src/libchcore/TDataBuffer.h (.../TDataBuffer.h) (revision b013066ba827b440b2e281bd58e8b16e51a080d7) +++ src/libchcore/TDataBuffer.h (.../TDataBuffer.h) (revision 2cc200f4b40dedfdebafab18bf07c733be47da8a) @@ -146,22 +146,34 @@ void ReleaseBuffer(TSimpleDataBuffer& rSimpleBuffer); private: - void FreeBuffers(); + void FreeAllAllocBlocks(); + // page handling bool CanAllocPage() const; // checks if a buffer can be returned after allocating new page of memory bool AllocNewPage(); void FreeAllocatedPages(size_t stPagesCount); - void FreePage(const details::TVirtualAllocMemoryBlockPtr& spAllocBlock); + bool FreePage(const details::TVirtualAllocMemoryBlockPtr& spAllocBlock); + void ReclaimPage(const details::TVirtualAllocMemoryBlockPtr& spAllocBlock); + void ReorganizePages(); private: + enum EBlockState + { + eBlock_Active, + eBlock_ToFree + }; + + typedef std::vector > MemoryBlocksVector; + #pragma warning(push) #pragma warning(disable: 4251) - std::vector m_vVirtualAllocBlocks; - std::vector m_vAllocBlocksToFree; + MemoryBlocksVector m_vVirtualAllocBlocks; std::list m_listUnusedBuffers; #pragma warning(pop) - + + size_t m_stAllocBlocksToFree; + size_t m_stMaxMemory; // maximum amount of memory to use size_t m_stPageSize; // size of a single page of real memory to be allocated (allocation granularity) size_t m_stBufferSize; // size of a single chunk of memory retrievable by caller Index: src/libchcore/Tests/TDataBufferManagerTest.cpp =================================================================== diff -u -r2e23b5892ef4d4bb1ee2c6cde893004a71a11510 -r2cc200f4b40dedfdebafab18bf07c733be47da8a --- src/libchcore/Tests/TDataBufferManagerTest.cpp (.../TDataBufferManagerTest.cpp) (revision 2e23b5892ef4d4bb1ee2c6cde893004a71a11510) +++ src/libchcore/Tests/TDataBufferManagerTest.cpp (.../TDataBufferManagerTest.cpp) (revision 2cc200f4b40dedfdebafab18bf07c733be47da8a) @@ -3,6 +3,38 @@ #include "gmock/gmock.h" #include "../TDataBuffer.h" +// fixtures +class BasicBufferFixture : public ::testing::Test +{ +protected: + virtual void SetUp() + { + size_t stMaxMemory = 1048034; + + chcore::TDataBufferManager::CheckBufferConfig(stMaxMemory); + tBufferManager.Initialize(stMaxMemory); + } + + chcore::TDataBufferManager tBufferManager; +}; + +class DetailedBufferFixture : public ::testing::Test +{ +protected: + virtual void SetUp() + { + size_t stMaxMemory = 1048034; + size_t stPageSize = 262144; + size_t stBufferSize = 65536; + + chcore::TDataBufferManager::CheckBufferConfig(stMaxMemory, stPageSize, stBufferSize); + + tBufferManager.Initialize(stMaxMemory, stPageSize, stBufferSize); + } + + chcore::TDataBufferManager tBufferManager; +}; + /////////////////////////////////////////////////////////////////////////////// // TSimpleDataBuffer @@ -55,7 +87,7 @@ TEST(TDataBufferManager, CheckBufferConfigExt) { // detailed config - default values - size_t stMaxMem = 0; + size_t stMaxMem(0); size_t stPageSize(0); size_t stChunkSize(0); EXPECT_EQ(chcore::TDataBufferManager::CheckBufferConfig(stMaxMem, stPageSize, stChunkSize), false); @@ -93,22 +125,8 @@ EXPECT_EQ(tBufferManager.GetMaxMemorySize(), chcore::TDataBufferManager::DefaultPageSize); } -class TInitializedBufferManager : public ::testing::Test +TEST_F(BasicBufferFixture, FailedResize) { -protected: - virtual void SetUp() - { - size_t stMaxMemory = 1048034; - - chcore::TDataBufferManager::CheckBufferConfig(stMaxMemory); - tBufferManager.Initialize(stMaxMemory); - } - - chcore::TDataBufferManager tBufferManager; -}; - -TEST_F(TInitializedBufferManager, FailedResize) -{ EXPECT_TRUE(tBufferManager.IsInitialized()); size_t stCurrentMaxSize = tBufferManager.GetMaxMemorySize(); @@ -122,7 +140,7 @@ EXPECT_EQ(stCurrentBufferSize, tBufferManager.GetSimpleBufferSize()); } -TEST_F(TInitializedBufferManager, ResizeToSameSizeWithSimpleBufferChecks) +TEST_F(BasicBufferFixture, ResizeToSameSizeWithSimpleBufferChecks) { EXPECT_TRUE(tBufferManager.IsInitialized()); EXPECT_EQ((tBufferManager.GetMaxMemorySize() / tBufferManager.GetSimpleBufferSize()), tBufferManager.GetCountOfFreeBuffers()); @@ -140,34 +158,8 @@ EXPECT_EQ((tBufferManager.GetMaxMemorySize() / tBufferManager.GetSimpleBufferSize()), tBufferManager.GetCountOfFreeBuffers()); } -class TInitializedBufferManager2 : public ::testing::Test +TEST_F(DetailedBufferFixture, SmallBufferOperations) { -protected: - virtual void SetUp() - { - size_t stMaxMemory = 1048034; - size_t stPageSize = 262144; - size_t stBufferSize = 65536; - - chcore::TDataBufferManager::CheckBufferConfig(stMaxMemory, stPageSize, stBufferSize); - - tBufferManager.Initialize(stMaxMemory, stPageSize, stBufferSize); - } - - chcore::TDataBufferManager tBufferManager; -}; - -TEST_F(TInitializedBufferManager2, SmallBufferOperations) -{ - // verify we get what we wanted to have - EXPECT_TRUE(tBufferManager.IsInitialized()); - EXPECT_EQ(tBufferManager.GetMaxMemorySize(), 1*1024*1024); - EXPECT_EQ(tBufferManager.GetPageSize(), 262144); - EXPECT_EQ(tBufferManager.GetSimpleBufferSize(), 65536); - EXPECT_EQ(tBufferManager.GetRealAllocatedMemorySize(), 262144); // only one page should be allocated at the moment - EXPECT_EQ(tBufferManager.GetCountOfFreeBuffersNA(), 4); - EXPECT_EQ(tBufferManager.GetCountOfFreeBuffers(), 16); - // get a single buffer, check internals chcore::TSimpleDataBuffer tBuffer; EXPECT_TRUE(tBufferManager.GetFreeBuffer(tBuffer)); @@ -179,17 +171,8 @@ EXPECT_EQ(tBufferManager.GetCountOfFreeBuffers(), 15); } -TEST_F(TInitializedBufferManager2, WithoutAdditionalAllocTest) +TEST_F(DetailedBufferFixture, WithoutAdditionalAllocTest) { - // verify we get what we wanted to have - EXPECT_TRUE(tBufferManager.IsInitialized()); - EXPECT_EQ(tBufferManager.GetMaxMemorySize(), 1*1024*1024); - EXPECT_EQ(tBufferManager.GetPageSize(), 262144); - EXPECT_EQ(tBufferManager.GetSimpleBufferSize(), 65536); - EXPECT_EQ(tBufferManager.GetRealAllocatedMemorySize(), 262144); // only one page should be allocated at the moment - EXPECT_EQ(tBufferManager.GetCountOfFreeBuffersNA(), 4); - EXPECT_EQ(tBufferManager.GetCountOfFreeBuffers(), 16); - // do this in separate scope to allow auto-release of buffers at the end { std::vector vBuffers; @@ -209,26 +192,19 @@ EXPECT_TRUE(tBufferManager.HasFreeBuffer()); } + // check that everything was freed EXPECT_EQ(tBufferManager.GetCountOfFreeBuffersNA(), 4); EXPECT_EQ(tBufferManager.GetCountOfFreeBuffers(), 16); EXPECT_EQ(tBufferManager.GetRealAllocatedMemorySize(), 262144); // only one page should be allocated at the moment EXPECT_TRUE(tBufferManager.HasFreeBuffer()); EXPECT_TRUE(tBufferManager.HasFreeBufferNA()); } -TEST_F(TInitializedBufferManager2, FullBufferTest) +TEST_F(DetailedBufferFixture, FullBufferTest) { - // verify we get what we wanted to have - EXPECT_TRUE(tBufferManager.IsInitialized()); - EXPECT_EQ(tBufferManager.GetMaxMemorySize(), 1*1024*1024); - EXPECT_EQ(tBufferManager.GetPageSize(), 262144); - EXPECT_EQ(tBufferManager.GetSimpleBufferSize(), 65536); - EXPECT_EQ(tBufferManager.GetRealAllocatedMemorySize(), 262144); // only one page should be allocated at the moment - EXPECT_EQ(tBufferManager.GetCountOfFreeBuffersNA(), 4); - EXPECT_EQ(tBufferManager.GetCountOfFreeBuffers(), 16); - // do this in separate scope to allow auto-release of buffers at the end { + // retrieve all the buffers that are inside std::vector vBuffers; for(size_t stIndex = 0; stIndex < 16; ++stIndex) { @@ -238,34 +214,28 @@ vBuffers.push_back(spBuf); } + // ensure everything was taken EXPECT_EQ(tBufferManager.GetCountOfFreeBuffersNA(), 0); EXPECT_EQ(tBufferManager.GetCountOfFreeBuffers(), 0); EXPECT_EQ(tBufferManager.GetRealAllocatedMemorySize(), 1024*1024); // only one page should be allocated at the moment EXPECT_FALSE(tBufferManager.HasFreeBufferNA()); EXPECT_FALSE(tBufferManager.HasFreeBuffer()); + // try to get one more buffer chcore::TSimpleDataBuffer tFailBuffer; EXPECT_FALSE(tBufferManager.GetFreeBuffer(tFailBuffer)); } + // ensure everything was freed as expected EXPECT_EQ(tBufferManager.GetCountOfFreeBuffers(), 16); EXPECT_EQ(tBufferManager.GetCountOfFreeBuffersNA(), 16); EXPECT_EQ(tBufferManager.GetRealAllocatedMemorySize(), 1024*1024); // only one page should be allocated at the moment EXPECT_TRUE(tBufferManager.HasFreeBufferNA()); EXPECT_TRUE(tBufferManager.HasFreeBuffer()); } -TEST_F(TInitializedBufferManager2, FullBufferWithResizeTest) +TEST_F(DetailedBufferFixture, FullBufferWithResizeTest) { - // verify we get what we wanted to have - EXPECT_TRUE(tBufferManager.IsInitialized()); - EXPECT_EQ(tBufferManager.GetMaxMemorySize(), 1*1024*1024); - EXPECT_EQ(tBufferManager.GetPageSize(), 262144); - EXPECT_EQ(tBufferManager.GetSimpleBufferSize(), 65536); - EXPECT_EQ(tBufferManager.GetRealAllocatedMemorySize(), 262144); // only one page should be allocated at the moment - EXPECT_EQ(tBufferManager.GetCountOfFreeBuffersNA(), 4); - EXPECT_EQ(tBufferManager.GetCountOfFreeBuffers(), 16); - // do this in separate scope to allow auto-release of buffers at the end { // get all buffers @@ -278,11 +248,7 @@ vBuffers.push_back(spBuf); } - // ensure nothing's left - chcore::TSimpleDataBuffer tFailBuffer; - EXPECT_FALSE(tBufferManager.GetFreeBuffer(tFailBuffer)); - - // now resize to half the size + // now resize to quarter the size size_t stNewSize = 262144; tBufferManager.CheckResizeSize(stNewSize); EXPECT_NO_FATAL_FAILURE(tBufferManager.ChangeMaxMemorySize(stNewSize)); @@ -293,15 +259,16 @@ EXPECT_EQ(tBufferManager.GetRealAllocatedMemorySize(), 1024*1024); // only one page should be allocated at the moment EXPECT_FALSE(tBufferManager.HasFreeBufferNA()); EXPECT_FALSE(tBufferManager.HasFreeBuffer()); - EXPECT_EQ(tBufferManager.GetMaxMemorySize(), 256*1024); + EXPECT_EQ(tBufferManager.GetMaxMemorySize(), 256*1024); // only a single page is available - // get rid of the small buffers (except one) + // get rid of the small buffers (except for one) for(size_t stIndex = 0; stIndex < 15; ++stIndex) { vBuffers.erase(vBuffers.end() - 1); } - // now only two pages should be left in buffer manage EXPECT_EQ(tBufferManager.GetCountOfFreeBuffers(), 3); + // now only one page should be left + EXPECT_EQ(tBufferManager.GetCountOfFreeBuffers(), 3); EXPECT_EQ(tBufferManager.GetCountOfFreeBuffersNA(), 3); EXPECT_EQ(tBufferManager.GetRealAllocatedMemorySize(), 256*1024); // only one page should be allocated at the moment EXPECT_TRUE(tBufferManager.HasFreeBufferNA());