WIP test covering the AllocationCluster draft

This commit is contained in:
Fischlurch 2008-10-20 06:27:14 +02:00
parent 490b7d163c
commit eaa89067bb
2 changed files with 205 additions and 8 deletions

View file

@ -76,11 +76,11 @@ namespace lib {
* aren't used after shutting down a given AllocationCluster.
*/
class AllocationCluster
: boost::noncopyable
{
public:
AllocationCluster ();
AllocationCluster (const AllocationCluster&);
~AllocationCluster () throw();
template<class TY>
@ -170,7 +170,7 @@ namespace lib {
void finishAlloc (PMemManager&, void*);
/** create a new MemoryManager implementation */
MemoryManager* setupMemoryManager (TypeInfo);
static MemoryManager* setupMemoryManager (TypeInfo const&);
};
@ -202,6 +202,7 @@ namespace lib {
get(ManagerTable& handlers)
{
ENSURE (id_ < handlers.size() || 1 <= handlers.size()); // 0th Element used as "undefined" marker
TODO ("this is very fishy and probably not threadsafe...!");
return handlers[id_<handlers.size()? id_ : 0 ];
}
@ -215,15 +216,19 @@ namespace lib {
if (id_ >= handlers.size())
handlers.resize(id_);
if (!handlers[id_])
handlers[id_].reset (setupMemoryManager (TypeInfo((TY*)0)));
{
TY* type_hint(0);
TypeInfo info (type_hint);
handlers[id_].reset (setupMemoryManager (info));
}
}
static void
kill (void* obj)
{
ASSERT (INSTANCEOF (TY,obj));
TY* p = static_cast<TY*>(obj);
ASSERT (p);
ASSERT (INSTANCEOF (TY,p));
p->~TY();
}
@ -243,17 +248,16 @@ namespace lib {
void*
AllocationCluster::allocation()
{
scoped_ptr<MemoryManager> typeHandler (TypeSlot<TY>::get (typeHandlers_));
if (!typeHandler)
if (!TypeSlot<TY>::get (typeHandlers_))
TypeSlot<TY>::setup (typeHandlers_);
return initiateAlloc (typeHandler);
return initiateAlloc (TypeSlot<TY>::get (typeHandlers_));
}
template<class TY>
TY&
AllocationCluster::commit (TY* obj)
{
scoped_ptr<MemoryManager> typeHandler (TypeSlot<TY>::get (typeHandlers_));
PMemManager & typeHandler (TypeSlot<TY>::get (typeHandlers_));
REQUIRE (typeHandler);
REQUIRE (obj);
finishAlloc (typeHandler, obj);

View file

@ -0,0 +1,193 @@
/*
AllocationCluster(Test) - verify bulk (de)allocating a family of objects
Copyright (C) Lumiera.org
2008, Hermann Vosseler <Ichthyostega@web.de>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
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 General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
* *****************************************************/
#include "common/test/run.hpp"
#include "common/util.hpp"
#include "lib/allocationcluster.hpp"
#include <vector>
#include <limits>
#include <boost/lexical_cast.hpp>
using boost::lexical_cast;
using util::for_each;
using util::isnil;
using ::Test;
using std::numeric_limits;
using std::vector;
namespace lib {
namespace test {
namespace { // a family of test dummy classes
uint NUM_CLUSTERS = 5;
uint NUM_OBJECTS = 500;
uint NUM_FAMILIES = 5;
long checksum = 0;
template<uint i>
class Dummy
{
char content[i];
public:
Dummy (char id)
{
content[0] = id;
checksum += id;
}
Dummy (char i1, char i2, char i3=0)
{
char id = i1 + i2 + i3;
content[0] = id;
if (0 == (rand() % 20))
throw id;
checksum += id;
}
~Dummy()
{
checksum -= content[0];
}
};
typedef vector<AllocationCluster> ClusterList;
inline char
truncChar (uint x)
{
return x % numeric_limits<char>::max();
}
template<uint i>
void
place_object (AllocationCluster& clu, uint id)
{
clu.create<Dummy<i> > (id);
}
typedef void (Invoker)(AllocationCluster&, uint);
Invoker* invoke[20] = { &place_object<1>
, &place_object<2>
, &place_object<3>
, &place_object<5>
, &place_object<10>
, &place_object<13>
, &place_object<14>
, &place_object<15>
, &place_object<16>
, &place_object<17>
, &place_object<18>
, &place_object<19>
, &place_object<20>
, &place_object<25>
, &place_object<30>
, &place_object<35>
, &place_object<40>
, &place_object<50>
, &place_object<100>
, &place_object<200>
};
void
fillIt (AllocationCluster& clu)
{
if (20<NUM_FAMILIES)
NUM_FAMILIES = 20;
for (uint i=0; i<NUM_OBJECTS; ++i)
{
char id = truncChar(i);
(*(invoke[rand() % NUM_FAMILIES])) (clu,id);
}
}
}
/*************************************************************************
* @test verify the proper workings of our custom allocation scheme
* managing families of interconnected objects for the segments
* of the low-level model.
*/
class AllocationCluster_test : public Test
{
virtual void
run (Arg arg)
{
if (0 < arg.size()) NUM_CLUSTERS = lexical_cast<uint> (arg[0]);
if (1 < arg.size()) NUM_OBJECTS = lexical_cast<uint> (arg[1]);
if (2 < arg.size()) NUM_FAMILIES = lexical_cast<uint> (arg[2]);
checkAllocation();
checkErrorHandling();
}
void
checkAllocation()
{
ASSERT (0==checksum);
{
ClusterList clusters (NUM_CLUSTERS);
for_each (clusters, fillIt);
ASSERT (0!=checksum);
}
ASSERT (0==checksum);
}
void
checkErrorHandling()
{
ASSERT (0==checksum);
{
AllocationCluster clu;
for (uint i=0; i<NUM_OBJECTS; ++i)
try
{
char i1 = truncChar(i);
char i2 = truncChar(rand() % 5);
clu.create<Dummy<1> > (i1,i2);
}
catch (char id)
{
checksum -= id;
}
}
ASSERT (0==checksum);
}
};
LAUNCHER (AllocationCluster_test, "unit common");
}// namespace test
} // namespace lib