Library: adapt further AllocationCluster tests

...especially demonstrate that destructors
can optionally be invoked or not invoked...
This commit is contained in:
Fischlurch 2024-05-27 21:21:03 +02:00
parent 178107e8b9
commit db4fbde201
3 changed files with 39 additions and 11 deletions

View file

@ -24,10 +24,14 @@
** Memory management for the low-level model (render nodes network).
** The model is organised into temporal segments, which are considered
** to be structurally constant and uniform. The objects within each
** segment are strongly interconnected, and thus each segment is
** created within a single build process and is replaced or released
** as a whole. AllocationCluster implements memory management to
** support this usage pattern.
** segment are strongly interconnected, and thus each segment is created
** within a single build process and is replaced or released as a whole.
** AllocationCluster implements memory management to support this usage
** pattern. Optionally it is even possible to skip invocation of object
** destructors, making de-allocation highly efficient (typically the
** memory pages are already cache-cold when about to discarded).
** @warning deliberately *not threadsafe*.
** @remark confine usage to a single thread or use thread-local clusters.
** @see allocation-cluster-test.cpp
** @see builder::ToolFactory
** @see linked-elements.hpp
@ -58,7 +62,7 @@ namespace lib {
* is to bulk-allocate memory, and to avoid invoking destructors (and thus to access
* a lot of _cache-cold memory pages_ on clean-up). A Stdlib compliant #Allocator
* is provided for use with STL containers. The actual allocation uses heap memory
* in _extents_ of hard-wired size, by the accompanying StorageManager.
* in _extents_ of hard-wired size, maintained by the accompanying StorageManager.
* @warning use #createDisposable whenever possible, but be sure to understand
* the ramifications of _not invoking_ an object's destructor.
*/

View file

@ -117,7 +117,12 @@ namespace lib {
construct (typename ALOT::allocator_type& allo, ARGS&& ...args)
{
auto loc = ALOT::allocate (allo, 1);
ALOT::construct (allo, loc, std::forward<ARGS>(args)...);
try { ALOT::construct (allo, loc, std::forward<ARGS>(args)...); }
catch(...)
{
ALOT::deallocate (allo, loc, 1);
throw;
}
return loc;
}

View file

@ -143,8 +143,8 @@ namespace test {
virtual void
run (Arg)
{
// simpleUsage();
// checkLifecycle();
simpleUsage();
checkLifecycle();
verifyInternals();
use_as_Allocator();
}
@ -154,25 +154,31 @@ namespace test {
simpleUsage()
{
AllocationCluster clu;
CHECK (0 == clu.numExtents());
char c1(123), c2(45);
Dummy<66>& ref1 = clu.create<Dummy<66>> ();
Dummy<77>& ref2 = clu.create<Dummy<77>> (c1);
Dummy<77>& ref3 = clu.create<Dummy<77>> (c2);
// TRACE (test, "%s", showSizeof(rX).c_str());///////////////////////OOO
//returned references actually point at the objects we created
CHECK (1 ==ref1.getID());
CHECK (123==ref2.getID());
CHECK (45 ==ref3.getID());
CHECK (1 == clu.numExtents());
CHECK (0 < clu.numExtents());
// now use objects and just let them go;
}
/** @test Allocation cluster grows when adding objects,
* but discards all objects at once when going out of scope,
* optionally also invoking (or not invoking) destructors.
* @remark no destructors are invoked for any objects allocated
* through the `createDisposable<TY>(args...)` interface,
* or for allocations though the standard allocator adapter.
*/
void
checkLifecycle()
{
@ -184,6 +190,19 @@ namespace test {
CHECK (0!=checksum);
}
CHECK (0==checksum);
int64_t allSum;
{// can also be used without invoking any destructors
AllocationCluster clu;
for (uint i=0; i<NUM_OBJECTS; ++i)
clu.createDisposable<Dummy<223>>();
CHECK (clu.numExtents() == NUM_OBJECTS);
CHECK (checksum == NUM_OBJECTS * 223);
allSum = checksum;
}// Memory discarded here without invoking any destructor....
CHECK (allSum == checksum);
checksum = 0;
}