Invocation: rearrange SeveralBuilder policy

redefine the policy for `lib::SeveralBuilder` to be a template-template parameter.
In fact it should have been this way from start, yet defining this kind of
very elaborate code bottom-up lets you sometime miss the wood for the trees

So to restate: `lib::SeveralBuilder` takes a ''policy template,''
which then in turn will be instantiated with the same types `I` (interface)
and `E` (element type) used on `SeveralBuilder` itself. Obviously, there can be
further types involved and thus additional type parameters may be necessary,
notably the ''Allocator'' — yet these are better injected when ''defining''
the policy template itself.

The default binding for this policy template is defined as `allo::HeapOwn`,
which causes the builder to allocate the storage extents through the standard
heap allocator, and for the created `lib::Several` to take full ownership of
embedded objects, invoking their destructors when falling out of scope.
This commit is contained in:
Fischlurch 2024-07-17 01:43:17 +02:00
parent 2fd3629d80
commit 1705c40dc2
4 changed files with 52 additions and 48 deletions

View file

@ -317,13 +317,11 @@ namespace lib {
//-----Policies-to-use-AllocationCluster------------------------
namespace {
namespace allo { // Setup for custom allocator policies
// Forward declaration: configuration policy for lib::SeveralBuilder
template<class I, class E, template<typename> class ALO>
struct AllocationPolicy;
}
namespace allo { // Setup for custom allocator policies
template<template<typename> class ALO, typename...ARGS>
struct SetupSeveral;

View file

@ -124,8 +124,7 @@ namespace lib {
using std::move;
using std::byte;
namespace {// Allocation management policies
namespace {
/** number of storage slots to open initially;
* starting with an over-allocation similar to `std::vector`
*/
@ -173,7 +172,10 @@ namespace lib {
{
return positiveDiff (alignment, alignof(void*));
}
}//(End)helpers
namespace allo {// Allocation management policies
/**
* Generic factory to manage objects within an ArrayBucket<I> storage,
@ -355,7 +357,7 @@ namespace lib {
template<class I, class E>
using HeapOwn = AllocationPolicy<I, E, std::allocator>;
}//(End)implementation details
}//(End) namespace several
@ -381,28 +383,29 @@ namespace lib {
* patterns, consistency checks may throw at runtime,
* when attempting to add an unsuitable element.
*/
template<class I ///< Interface or base type visible on resulting Several<I>
,class E =I ///< a subclass element element type (relevant when not trivially movable and destructible)
,class POL =HeapOwn<I,E> ///< Allocator policy
template<class I ///< Interface or base type visible on resulting Several<I>
,class E =I ///< a subclass element element type (relevant when not trivially movable and destructible)
,template<class,class> class POL =allo::HeapOwn ///< Allocator policy template (parametrised `POL<I,E>`)
>
class SeveralBuilder
: private Several<I>
, util::MoveOnly
, POL
, POL<I,E>
{
using Coll = Several<I>;
using Policy = POL<I,E>;
using Bucket = ArrayBucket<I>;
using Bucket = several::ArrayBucket<I>;
using Deleter = typename Bucket::Deleter;
public:
SeveralBuilder() = default;
/** start Several build using a custom allocator */
template<typename...ARGS, typename = meta::enable_if<std::is_constructible<POL,ARGS...>>>
template<typename...ARGS, typename = meta::enable_if<std::is_constructible<Policy,ARGS...>>>
SeveralBuilder (ARGS&& ...alloInit)
: Several<I>{}
, POL{forward<ARGS> (alloInit)...}
, Policy{forward<ARGS> (alloInit)...}
{ }
@ -549,7 +552,7 @@ namespace lib {
adjustStorage (newCnt, max (elmSiz, Coll::spread()));
ENSURE (Coll::data_);
ensureDeleter<TY>();
POL::template createAt<TY> (Coll::data_, newPos, forward<ARGS> (args)...);
Policy::template createAt<TY> (Coll::data_, newPos, forward<ARGS> (args)...);
Coll::data_->cnt = newPos+1;
}
@ -583,7 +586,7 @@ namespace lib {
{
if (not (Coll::empty()
or Coll::hasReserve (requiredSiz, newElms)
or POL::canExpand (Coll::data_, requiredSiz*(Coll::size() + newElms))
or Policy::canExpand (Coll::data_, requiredSiz*(Coll::size() + newElms))
or canDynGrow()))
throw err::Invalid{_Fmt{"Several-container is unable to accommodate further element of type %s; "
"storage reserve (%d bytes ≙ %d elms) exhausted and unable to move "
@ -607,7 +610,7 @@ namespace lib {
size_t overhead = sizeof(Bucket) + alignRes(alignof(E));
size_t safetyLim = LUMIERA_MAX_ORDINAL_NUMBER * Coll::spread();
size_t expandAlloc = min (positiveDiff (min (safetyLim
,POL::ALLOC_LIMIT)
,Policy::ALLOC_LIMIT)
,overhead)
,max (2*buffSiz, cnt*spread));
// round down to an even number of elements
@ -618,7 +621,7 @@ namespace lib {
"exceeds safety limit of %d bytes"} % safetyLim
,LERR_(SAFETY_LIMIT)};
// allocate new storage block...
Coll::data_ = POL::realloc (Coll::data_, newCnt,spread);
Coll::data_ = Policy::realloc (Coll::data_, newCnt,spread);
}
ENSURE (Coll::data_);
if (canWildMove() and spread != Coll::spread())
@ -629,11 +632,11 @@ namespace lib {
fitStorage()
{
REQUIRE (not Coll::empty());
if (not (POL::canExpand (Coll::data_, Coll::size())
if (not (Policy::canExpand (Coll::data_, Coll::size())
or canDynGrow()))
throw err::Invalid{"Unable to shrink storage for Several-collection, "
"since at least one element can not be moved."};
Coll::data_ = POL::realloc (Coll::data_, Coll::size(), Coll::spread());
Coll::data_ = Policy::realloc (Coll::data_, Coll::size(), Coll::spread());
}
/** move existing data to accommodate spread */
@ -709,7 +712,7 @@ namespace lib {
Deleter
selectDestructor()
{
typename POL::Fac& factory(*this);
typename Policy::Fac& factory(*this);
if (is_Subclass<TY,I>() and has_virtual_destructor_v<I>)
{
@ -831,7 +834,7 @@ namespace lib {
* @see lib::AllocationCluster (which provides a custom adaptation)
* @see SeveralBuilder_test::check_CustomAllocator()
*/
template<class I, class E, class POL>
template<class I, class E, template<class,class> class POL>
template<template<typename> class ALO, typename...ARGS>
inline auto
SeveralBuilder<I,E,POL>::withAllocator (ARGS&& ...args)
@ -841,8 +844,7 @@ namespace lib {
"prior to adding any elements to the container"};
using Setup = allo::SetupSeveral<ALO,ARGS...>;
using PolicyForAllo = typename Setup::template Policy<I,E>;
using BuilderWithAllo = SeveralBuilder<I,E,PolicyForAllo>;
using BuilderWithAllo = SeveralBuilder<I,E, Setup::template Policy>;
return BuilderWithAllo(forward<ARGS> (args)...);
}

View file

@ -118,7 +118,7 @@ namespace engine {
using PolicyForAllo = typename Setup::template Policy<I,E>;
template<class I, class E=I>
using BuilderType = lib::SeveralBuilder<I,E, PolicyForAllo<I,E>>;
using BuilderType = lib::SeveralBuilder<I,E, PolicyForAllo>;
};
struct UseHeapAlloc

View file

@ -2805,9 +2805,7 @@
<icon BUILTIN="button_ok"/>
<node CREATED="1534636352398" ID="ID_435790811" MODIFIED="1538263469671" TEXT="&#xe4;hnliche Lage wie bei Destroy">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
GTK bietet nur Anzeigen von top-down:
@ -3123,9 +3121,7 @@
<icon BUILTIN="button_ok"/>
<node COLOR="#435e98" CREATED="1538281532767" ID="ID_1335570495" MODIFIED="1538365732115" TEXT="Fehler: mu&#xdf; eigens separate GenNode bauen">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
...weil der Payload-Typ f&#252;r diesen Aufruf bool ist,
@ -3142,9 +3138,7 @@
<icon BUILTIN="button_ok"/>
<node CREATED="1538281635897" FOLDED="true" ID="ID_562945035" MODIFIED="1561827464647" TEXT="lexical_cast geht nicht">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
k
@ -5000,9 +4994,7 @@
</node>
<node CREATED="1482466197707" ID="ID_832611965" MODIFIED="1518487921059">
<richcontent TYPE="NODE"><html>
<head>
</head>
<head/>
<body>
<p>
Architektur-Entscheidung
@ -7319,9 +7311,7 @@
</node>
<node CREATED="1506180752103" ID="ID_1985524064" MODIFIED="1576282358128" TEXT="starting point">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
navigate to the real UI component
@ -10760,9 +10750,7 @@
</node>
<node COLOR="#338800" CREATED="1512621101645" ID="ID_1982135306" MODIFIED="1512789977343" TEXT="Polymorphie: verschiedene Pipelines">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
verschiedendste Pipeline-Konstruktionen
@ -87719,8 +87707,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
Alle Typen sind bekannt und bereits angeschrieben; die neulich gefundene L&#246;sung mit dem decltype(&lt;builder&gt;)-Trick hat mich zwar zum Ziel gebracht, ist aber unn&#246;tig indirekt &#8212; man k&#246;nnte durchaus die Typen ineinander einsetzen und dann in eine einzige Typedef reduzieren
</p>
</body>
</html>
</richcontent>
</html></richcontent>
<icon BUILTIN="button_cancel"/>
<node CREATED="1721174638056" ID="ID_1423112088" MODIFIED="1721174644592" TEXT="nein: doch nicht ganz..."/>
<node CREATED="1721174645372" ID="ID_940405790" MODIFIED="1721174658046" TEXT="es geht schon um die Anordnung der Typ-Parameter"/>
@ -87733,8 +87720,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
Namens-Idee: <b>AlloPolicySelector</b>
</p>
</body>
</html>
</richcontent>
</html></richcontent>
<icon BUILTIN="idea"/>
<node CREATED="1721171183918" ID="ID_1312928828" MODIFIED="1721174829989" TEXT="aber... das ist doch genau allo::SetupSeveral&lt;ALO,ARGS...&gt;">
<arrowlink COLOR="#fefcc9" DESTINATION="ID_1620829594" ENDARROW="Default" ENDINCLINATION="-60;-64;" ID="Arrow_ID_864095772" STARTARROW="None" STARTINCLINATION="-82;4;"/>
@ -87758,6 +87744,24 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<node CREATED="1721174156169" ID="ID_137493922" MODIFIED="1721174261682" TEXT="erbt von einfachem Typ-Parameter &#x2014; obwohl ein Template-Template w&#xfc;nschenswert w&#xe4;re">
<icon BUILTIN="messagebox_warning"/>
</node>
<node COLOR="#338800" CREATED="1721179318436" ID="ID_697938671" MODIFIED="1721179370879" TEXT="Nachbessern: die Policy f&#xfc;r lib::SeveralBuilder als template-template definieren">
<icon BUILTIN="yes"/>
<node CREATED="1721179377547" ID="ID_911419354" MODIFIED="1721179383494" TEXT="das ist nur Flei&#xdf;arbeit"/>
<node CREATED="1721179384227" ID="ID_1249905366" MODIFIED="1721179507877" TEXT="und in jedem Fall viel klarer so">
<icon BUILTIN="idea"/>
</node>
<node COLOR="#435e98" CREATED="1721179392209" ID="ID_1920236724" MODIFIED="1721179501907" TEXT="Sollte dann auch die AllocationPolicy in einen benannten Namespace legen">
<richcontent TYPE="NOTE"><html>
<head/>
<body>
<p>
es bieteten sich an: <font face="Monospaced" color="#5c1818">lib::several </font>und<font face="Monospaced" color="#5c1818">&#160;lib::allo</font>&#160;&#10229; letzteres ist logischer!
</p>
</body>
</html>
</richcontent>
</node>
</node>
</node>
</node>
<node COLOR="#338800" CREATED="1721174754965" ID="ID_1620829594" MODIFIED="1721175429658" TEXT="Nebenschauplatz: den decltype()-Trick eliminieren">