#i105938# Provides simplistic pool memory from a std::vector

This commit is contained in:
thb
2009-10-16 00:48:23 +02:00
parent 1837a267a2
commit 44dfc8de1a
3 changed files with 206 additions and 0 deletions

View File

@@ -0,0 +1,132 @@
/*************************************************************************
*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* Copyright 2008 by Sun Microsystems, Inc.
*
* OpenOffice.org - a multi-platform office productivity suite
*
* $RCSfile: lazy_update.hxx,v $
* $Revision: 1.3 $
*
* This file is part of OpenOffice.org.
*
* OpenOffice.org is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License version 3
* only, as published by the Free Software Foundation.
*
* OpenOffice.org 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 Lesser General Public License version 3 for more details
* (a copy is included in the LICENSE file that accompanied this code).
*
* You should have received a copy of the GNU Lesser General Public License
* version 3 along with OpenOffice.org. If not, see
* <http://www.openoffice.org/license.html>
* for a copy of the LGPLv3 License.
*
************************************************************************/
#ifndef INCLUDED_O3TL_VECTOR_POOL_HXX
#define INCLUDED_O3TL_VECTOR_POOL_HXX
#include <sal/types.h>
#include <vector>
namespace o3tl
{
namespace detail
{
template<typename ValueType, class Container> class simple_pool_impl :
public Container
{
typedef typename Container::value_type value_type;
std::ptrdiff_t mnFirstFreeIndex;
public:
simple_pool_impl() :
mnFirstFreeIndex(-1)
{}
std::ptrdiff_t alloc()
{
return store(ValueType());
}
std::ptrdiff_t store(const ValueType& rCopy)
{
if( mnFirstFreeIndex != -1 )
{
std::ptrdiff_t nIdx=mnFirstFreeIndex;
mnFirstFreeIndex = this->at(mnFirstFreeIndex).nextFree;
this->at(nIdx).value = rCopy;
this->at(nIdx).nextFree = -1;
return nIdx;
}
else
{
push_back(value_type(rCopy));
return this->size()-1;
}
}
void free( std::ptrdiff_t nIdx )
{
this->at(nIdx).nextFree = mnFirstFreeIndex;
mnFirstFreeIndex = nIdx;
}
const ValueType& get( std::ptrdiff_t nIdx ) const
{
return this->operator[](nIdx).value;
}
ValueType& get( std::ptrdiff_t nIdx )
{
return this->operator[](nIdx).value;
}
};
template< typename ValueType > struct struct_from_value
{
struct type
{
type() :
value(),
nextFree(-1)
{}
explicit type( const ValueType& val ) :
value(val),
nextFree(-1)
{}
ValueType value;
std::ptrdiff_t nextFree;
};
};
}
/** Simple vector-based memory pool allocator
This template can be used to provide simple pooled memory
allocation from a container class that adheres to the stl
random access container concept. Note that alloc/free works
with _indices_ into the container!
@example
<pre>
vector_pool<type> myPool;
int nIdx=myPool.alloc();
myPool[nIdx] = myVal;
... do stuff ...
myPool.free(nIdx);
</pre>
*/
template<typename ValueType> struct vector_pool :
public detail::simple_pool_impl<ValueType,
std::vector<typename detail::struct_from_value<ValueType>::type > >
{};
}
#endif /* INCLUDED_O3TL_VECTOR_POOL_HXX */

View File

@@ -46,6 +46,7 @@ ENABLE_EXCEPTIONS=TRUE
SHL1OBJS= \
$(SLO)$/cow_wrapper_clients.obj \
$(SLO)$/test-cow_wrapper.obj \
$(SLO)$/test-vector_pool.obj \
$(SLO)$/test-heap_ptr.obj \
$(SLO)$/test-range.obj

View File

@@ -0,0 +1,73 @@
// autogenerated file with codegen.pl
#include <cppunit/simpleheader.hxx>
#include <o3tl/vector_pool.hxx>
using namespace ::o3tl;
class vector_pool_test : public CppUnit::TestFixture
{
public:
void testPoolBasics()
{
vector_pool<int> aPool;
std::ptrdiff_t nIdx1 = aPool.alloc();
std::ptrdiff_t nIdx2 = aPool.alloc();
std::ptrdiff_t nIdx3 = aPool.alloc();
CPPUNIT_ASSERT_MESSAGE("allocator idx order 1", nIdx1 < nIdx2 );
CPPUNIT_ASSERT_MESSAGE("allocator idx order 2", nIdx2 < nIdx3 );
aPool.free(nIdx2);
aPool.free(nIdx3);
nIdx2 = aPool.alloc();
nIdx3 = aPool.alloc();
CPPUNIT_ASSERT_MESSAGE("allocator idx order 1 after fragmentation", nIdx1 < nIdx3 );
CPPUNIT_ASSERT_MESSAGE("allocator idx order 2 after fragmentation", nIdx3 < nIdx2 );
}
void testPoolValueSemantics()
{
vector_pool<int> aPool;
std::ptrdiff_t nIdx1 = aPool.store(0);
CPPUNIT_ASSERT_MESSAGE("allocator value semantics 1", aPool.get(nIdx1) == 0 );
std::ptrdiff_t nIdx2 = aPool.store(1);
CPPUNIT_ASSERT_MESSAGE("allocator value semantics 2", aPool.get(nIdx2) == 1 );
std::ptrdiff_t nIdx3 = aPool.store(2);
CPPUNIT_ASSERT_MESSAGE("allocator value semantics 3", aPool.get(nIdx3) == 2 );
aPool.free(nIdx2);
aPool.free(nIdx3);
nIdx2 = aPool.store(1);
CPPUNIT_ASSERT_MESSAGE("allocator value semantics 2 after fragmentation", aPool.get(nIdx2) == 1 );
nIdx3 = aPool.store(2);
CPPUNIT_ASSERT_MESSAGE("allocator value semantics 3 after fragmentation", aPool.get(nIdx3) == 2 );
}
// Change the following lines only, if you add, remove or rename
// member functions of the current class,
// because these macros are need by auto register mechanism.
CPPUNIT_TEST_SUITE(vector_pool_test);
CPPUNIT_TEST(testPoolBasics);
CPPUNIT_TEST(testPoolValueSemantics);
CPPUNIT_TEST_SUITE_END();
};
// -----------------------------------------------------------------------------
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(vector_pool_test, "vector pool test");
// -----------------------------------------------------------------------------
// NOADDITIONAL;