comment, add to testsuite

This commit is contained in:
Fischlurch 2008-10-30 04:34:05 +01:00
parent b475fd0979
commit 57ccc289b0
5 changed files with 65 additions and 35 deletions

View file

@ -1,5 +1,5 @@
/*
AllocationCluster - allocating and owning a pile of objects
AllocationCluster - allocating and owning a pile of objects
Copyright (C) Lumiera.org
2008, Hermann Vosseler <Ichthyostega@web.de>
@ -25,9 +25,8 @@
#include "common/error.hpp"
#include "common/util.hpp"
using util::isnil;
//using util::cStr;
namespace lib {
@ -47,7 +46,7 @@ namespace lib {
* the dtor without actually knowing the object's type.
*
* @todo this is a preliminary or pseudo-implementation based on
* a vector of smart pointers, i.e. actually the objects are heap
* a vector of raw pointers, i.e. actually the objects are heap
* allocated. What actually should happen is for the MemoryManager to
* allocate raw memory chunk wise, sub partition it and place the objects
* into this private memory buffer. Further, possibly we could maintain
@ -76,7 +75,7 @@ namespace lib {
private:
void clearStorage();
};
void
@ -98,7 +97,7 @@ namespace lib {
AllocationCluster::MemoryManager::purge()
{
Thread::Lock<MemoryManager> guard SIDEEFFECT;
REQUIRE (type_.killIt, "we need a deleter function");
REQUIRE (0 < type_.allocSize, "allocation size unknown");
REQUIRE (top_ == mem_.size() || (top_+1) == mem_.size());
@ -116,7 +115,7 @@ namespace lib {
delete[] mem_[--i];
mem_.clear();
}
inline void*
AllocationCluster::MemoryManager::allocate()
@ -125,10 +124,11 @@ namespace lib {
REQUIRE (0 < type_.allocSize);
REQUIRE (top_ <= mem_.size());
if (top_==mem_.size())
mem_.resize(top_+1);
if (!mem_[top_])
if (!mem_[top_]) // re-use existing allocation, if any
mem_[top_] = new char[type_.allocSize];
ENSURE (top_ < mem_.size());
@ -141,7 +141,7 @@ namespace lib {
AllocationCluster::MemoryManager::commit (void* pendingAlloc)
{
Thread::Lock<MemoryManager> guard SIDEEFFECT;
REQUIRE (pendingAlloc);
ASSERT (top_ < mem_.size());
ASSERT (pendingAlloc == mem_[top_], "allocation protocol violated");
@ -155,8 +155,8 @@ namespace lib {
/** storage for static bookkeeping of type allocation slots */
size_t AllocationCluster::maxTypeIDs;
/** creating a new AllocationCluster prepares a table capable
* of holding the individual object families to come. Each of those
* is managed by a separate instance of the low-level memory manager.
@ -224,7 +224,7 @@ namespace lib {
}
ASSERT (handler(slot));
return initiateAlloc(slot);
return initiateAlloc(slot);
}

View file

@ -1,5 +1,5 @@
/*
ALLOCATIONCLUSTER.hpp - allocating and owning a pile of objects
ALLOCATIONCLUSTER.hpp - allocating and owning a pile of objects
Copyright (C) Lumiera.org
2008, Hermann Vosseler <Ichthyostega@web.de>
@ -53,7 +53,6 @@
#include "common/multithread.hpp"
#include "common/error.hpp"
//#include "common/util.hpp"
#include "lib/scopedholder.hpp"
#include "lib/scopedholdertransfer.hpp"
@ -69,11 +68,14 @@ namespace lib {
* Each of those contains a initially undetermined (but rather large)
* number of individual objects, which can be expected to be allocated
* within a short timespan and which are to be released cleanly on
* destruction of the AllocationCluster. There is a service creating
* individual objects with arbitrary ctor parameters and it is possible
* to control the oder in which the object families are to be discarded.
* destruction of the AllocationCluster. We provide a service creating
* individual objects with arbitrary ctor parameters.
* @warning make sure the objects dtors aren't called and object references
* aren't used after shutting down a given AllocationCluster.
* @todo implement a facility to control the oder in which
* the object families are to be discarded. Currently
* they are just purged in reverse order defined by
* the first request for allocating a certain type.
*/
class AllocationCluster
: boost::noncopyable
@ -83,6 +85,7 @@ namespace lib {
AllocationCluster ();
~AllocationCluster () throw();
template<class TY>
TY&
create ()
@ -122,7 +125,7 @@ namespace lib {
TY* obj = new(allocation<TY>()) TY (p0,p1,p2,p3);
return commit(obj);
}
private:
/** initiate an allocation for the given type */
@ -160,7 +163,9 @@ namespace lib {
typedef ScopedPtrHolder<MemoryManager> HMemManager;
typedef Allocator_TransferNoncopyable<HMemManager> Allo;
typedef std::vector<HMemManager,Allo> ManagerTable;
ManagerTable typeHandlers_;
ManagerTable typeHandlers_; ///< table of active MemoryManager instances
HMemManager&
handler (size_t slot)
@ -174,7 +179,7 @@ namespace lib {
void* initiateAlloc (size_t& slot);
void* initiateAlloc (TypeInfo type, size_t& slot);
/** enrol the allocation after successful ctor call */
/** enrol the allocation after successful ctor call */
void finishAlloc (size_t& slot, void*);
};
@ -188,7 +193,7 @@ namespace lib {
struct AllocationCluster::TypeInfo
{
size_t allocSize;
void (*killIt)(void*);
void (*killIt)(void*); ///< deleter function
template<class TY>
TypeInfo(TY*)
@ -203,11 +208,11 @@ namespace lib {
};
template<class TY>
struct AllocationCluster::TypeSlot
{
static size_t id_; ///< table pos of the memory manager in charge for type TY
static size_t id_; ///< table pos+1 of the memory manager in charge for type TY
static size_t &
get()
@ -241,7 +246,7 @@ namespace lib {
template<class TY>
size_t AllocationCluster::TypeSlot<TY>::id_;
template<class TY>
inline void*
@ -253,7 +258,7 @@ namespace lib {
ENSURE (mem);
return mem;
}
template<class TY>
inline TY&
AllocationCluster::commit (TY* obj)

View file

@ -10,6 +10,11 @@ return: 0
END
TEST "AllocationCluster_test" AllocationCluster_test <<END
return: 0
END
TEST "Appconfig_test" Appconfig_test <<END
return: 0
END
@ -274,7 +279,19 @@ END
TEST "ScopedHolderTransfer_test" ScopedHolderTransfer_test <<END
out: checking ScopedHolder<Dummy>...
out: .
out: ..install one element at index[0]
out: .
out: ..*** resize table to 16 elements
out: .
out: .throw some exceptions...
out: checking ScopedPtrHolder<Dummy>...
out: .
out: ..install one element at index[0]
out: .
out: ..*** resize table to 16 elements
out: .
out: .throw some exceptions...
END

View file

@ -40,6 +40,8 @@ using ::Test;
using std::numeric_limits;
using std::vector;
namespace lib {
namespace test {
@ -49,7 +51,8 @@ namespace lib {
uint NUM_OBJECTS = 500;
uint NUM_FAMILIES = 5;
long checksum = 0;
long checksum = 0; // validate proper pairing of ctor/dtor calls
bool randomFailures = false;
template<uint i>
class Dummy
@ -67,7 +70,7 @@ namespace lib {
char id = i1 + i2 + i3;
content[0] = id;
checksum += id;
if (0 == (rand() % 20))
if (randomFailures && 0 == (rand() % 20))
throw id;
}
@ -137,6 +140,7 @@ namespace lib {
}
/*************************************************************************
* @test verify the proper workings of our custom allocation scheme
* managing families of interconnected objects for the segments
@ -182,6 +186,7 @@ namespace lib {
// all created objects dtors will be invoked.
}
void
checkAllocation()
{
@ -194,11 +199,14 @@ namespace lib {
ASSERT (0==checksum);
}
void
checkErrorHandling()
{
ASSERT (0==checksum);
{
randomFailures = true;
AllocationCluster clu;
for (uint i=0; i<NUM_OBJECTS; ++i)
try
@ -212,14 +220,14 @@ namespace lib {
checksum -= id; // exception thrown from within constructor,
} // thus dtor won't be called. Repair the checksum!
}
randomFailures = false;
ASSERT (0==checksum);
}
};
LAUNCHER (AllocationCluster_test, "unit common");
}// namespace test
} // namespace lib
}// namespace test
} // namespace lib

View file

@ -159,7 +159,7 @@ namespace lib {
table.reserve(2);
ASSERT (0==checksum);
cout << "\n..install one element at index[0]\n";
cout << ".\n..install one element at index[0]\n";
table.push_back(HO());
ASSERT (0==checksum);
@ -167,7 +167,7 @@ namespace lib {
ASSERT (0 < checksum);
int theSum = checksum;
cout << "\n..*** resize table to 16 elements\n";
cout << ".\n..*** resize table to 16 elements\n";
for (uint i=0; i<15; ++i)
table.push_back(HO());
@ -194,7 +194,7 @@ namespace lib {
ASSERT (0 < checksum);
int theSum = checksum;
cout << "\n.throw some exceptions...\n";
cout << ".\n.throw some exceptions...\n";
throw_in_ctor = true;
try
{