diff --git a/src/lib/allocationcluster.hpp b/src/lib/allocationcluster.hpp index f9c63eccf..d9ce5d660 100644 --- a/src/lib/allocationcluster.hpp +++ b/src/lib/allocationcluster.hpp @@ -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 @@ -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()) 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(obj); ASSERT (p); + ASSERT (INSTANCEOF (TY,p)); p->~TY(); } @@ -243,17 +248,16 @@ namespace lib { void* AllocationCluster::allocation() { - scoped_ptr typeHandler (TypeSlot::get (typeHandlers_)); - if (!typeHandler) + if (!TypeSlot::get (typeHandlers_)) TypeSlot::setup (typeHandlers_); - return initiateAlloc (typeHandler); + return initiateAlloc (TypeSlot::get (typeHandlers_)); } template TY& AllocationCluster::commit (TY* obj) { - scoped_ptr typeHandler (TypeSlot::get (typeHandlers_)); + PMemManager & typeHandler (TypeSlot::get (typeHandlers_)); REQUIRE (typeHandler); REQUIRE (obj); finishAlloc (typeHandler, obj); diff --git a/tests/common/allocationclustertest.cpp b/tests/common/allocationclustertest.cpp new file mode 100644 index 000000000..d9fc1ddad --- /dev/null +++ b/tests/common/allocationclustertest.cpp @@ -0,0 +1,193 @@ +/* + AllocationCluster(Test) - verify bulk (de)allocating a family of objects + + Copyright (C) Lumiera.org + 2008, Hermann Vosseler + + 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 +#include +#include + +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 + 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 ClusterList; + + inline char + truncChar (uint x) + { + return x % numeric_limits::max(); + } + + template + void + place_object (AllocationCluster& clu, uint id) + { + clu.create > (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 (arg[0]); + if (1 < arg.size()) NUM_OBJECTS = lexical_cast (arg[1]); + if (2 < arg.size()) NUM_FAMILIES = lexical_cast (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 > (i1,i2); + } + catch (char id) + { + checksum -= id; + } + } + ASSERT (0==checksum); + } + }; + + LAUNCHER (AllocationCluster_test, "unit common"); + + + }// namespace test + +} // namespace lib +