comment, add to testsuite
This commit is contained in:
parent
b475fd0979
commit
57ccc289b0
5 changed files with 65 additions and 35 deletions
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in a new issue