Library: rearrange logic for trivial move detection

...still fighting to get the design of the `AllocationPolicy`
settled to work well with `AllocationCluster` while also allowing
to handle data types which are (not) trivially copyable.

This changeset attempts to turn the logic round: now we capture
an ''move exclusion flag'' and otherwise allow the Policy to
decide on its own, based on the ''element type''
This commit is contained in:
Fischlurch 2024-06-08 21:58:04 +02:00
parent 446f133c09
commit 3a263c8c63
2 changed files with 83 additions and 44 deletions

View file

@ -146,7 +146,7 @@ namespace lib {
};
template<class I, template<typename> class ALO>
template<class I, class E, template<typename> class ALO>
struct AllocationPolicy
: ElementFactory<I, ALO>
{
@ -205,53 +205,54 @@ namespace lib {
}
return newBucket;
}
// // ensure sufficient storage or verify the ability to re-allocate
// if (not (Coll::hasReserve(sizeof(TY))
// or POL::canExpand(sizeof(TY))
// or handling_.template canDynGrow<TY>()))
// throw err::Invalid{_Fmt{"Unable to accommodate further element of type %s "}
// % util::typeStr<TY>()};
}
};
template<class I>
using HeapOwn = AllocationPolicy<I, std::allocator>;
template<class I, class E>
using HeapOwn = AllocationPolicy<I, E, std::allocator>;
using std::is_trivially_move_constructible_v;
using std::is_trivially_destructible_v;
using std::has_virtual_destructor_v;
using std::is_trivially_copyable_v;
using std::is_same_v;
using lib::meta::is_Subclass;
template<class I, class E>
struct HandlingStrategy
{
bool disposable :1 ;
bool wild_move :1 ;
bool disposable ;
bool lock_move ;
HandlingStrategy (bool unmanaged)
: disposable{unmanaged or (is_trivially_destructible_v<E> and
is_trivially_destructible_v<I>)}
, wild_move{false}
, lock_move{false}
{ }
/** mark that we're about to accept an otherwise unknown type,
* which can be trivially moved (by `memmove`). This irrevocably
* enables low-level`memove` usage for this container instance */
* which can not be trivially moved. This irrevocably disables
* relocations by low-level `memove` for this container instance */
template<typename TY>
bool
markWildMovePossibility()
void
probeMoveCapability()
{
if (wild_move and not isWildMoveCapable<TY>())
return false; // must reject, since it can not wild-moved
if (isWildMoveCapable<TY>()
and is_trivially_move_constructible_v<E>
and is_trivially_move_constructible_v<I>)
wild_move = true;
return true; // accept anyway (not sure yet if it must be moved)
if (not (is_same_v<TY,E> or is_trivially_copyable_v<TY>))
lock_move = true;
}
template<typename TY>
bool
isWildMoveCapable()
canWildMove()
{
return not (is_same_v<TY,E> or is_same_v<TY,I>)
and is_trivially_move_constructible_v<TY>;
return is_trivially_copyable_v<E> and not lock_move;
}
@ -265,13 +266,6 @@ namespace lib {
or (is_same_v<TY,E> and is_Subclass<E,I>());
}
template<typename TY>
bool
canDynGrow()
{
return is_same_v<TY,E> or wild_move;
}
auto
getDeleter()
{
@ -289,9 +283,9 @@ namespace lib {
* Wrap a vector holding objects of a subtype and
* provide array-like access using the interface type.
*/
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> ///< 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)
,class POL =HeapOwn<I,E> ///< Allocator policy
>
class SeveralBuilder
: Several<I>
@ -402,25 +396,15 @@ namespace lib {
throw err::Invalid{_Fmt{"Unable to handle destructor for element type %s"}
% util::typeStr<TY>()};
// mark acceptance of trivially movable arbitrary data types
if (not handling_.template markWildMovePossibility<TY>())
throw err::Invalid{_Fmt{"Unable to trivially move element type %s, "
"while other elements in this container are trivially movable."}
% util::typeStr<TY>()};
// mark when target type is not trivially movable
handling_.template probeMoveCapability<TY>();
// ensure sufficient element capacity or the ability to adapt element spread
if (Coll::spread() < sizeof(TY) and not (Coll::empty() or handling_.wild_move))
if (Coll::spread() < sizeof(TY) and not (Coll::empty() or handling_.canWildMove()))
throw err::Invalid{_Fmt{"Unable to place element of type %s (size=%d)"
"into container for element size %d."}
% util::typeStr<TY>() % sizeof(TY) % Coll::spread()};
// ensure sufficient storage or verify the ability to re-allocate
if (not (Coll::hasReserve(sizeof(TY))
or POL::canExpand(sizeof(TY))
or handling_.template canDynGrow<TY>()))
throw err::Invalid{_Fmt{"Unable to accommodate further element of type %s "}
% util::typeStr<TY>()};
size_t elmSiz = sizeof(TY);
size_t newCnt = Coll::size()+1;
adjustStorage (newCnt, max (elmSiz, Coll::spread()));

View file

@ -82598,6 +82598,61 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<icon BUILTIN="yes"/>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1717871024427" ID="ID_554783908" MODIFIED="1717871036535" TEXT="Aufteilung der Funktionalit&#xe4;t">
<icon BUILTIN="yes"/>
<node CREATED="1717871092594" ID="ID_207458820" MODIFIED="1717871140551" TEXT="Basis-Aktionen">
<node CREATED="1717871217897" ID="ID_925096747" MODIFIED="1717871229116" TEXT="Festlegen Zielpuffergr&#xf6;&#xdf;e"/>
<node CREATED="1717871230816" ID="ID_1183913040" MODIFIED="1717871323010" TEXT="bestehenden Puffer in der Gr&#xf6;&#xdf;e justieren"/>
<node CREATED="1717871324116" ID="ID_1761060700" MODIFIED="1717871329806" TEXT="neuen Puffer belegen"/>
<node CREATED="1717871330514" ID="ID_260028972" MODIFIED="1717871362218" TEXT="Elemente per Konstruktor umkopieren alt &#x27f6; neu"/>
<node CREATED="1717871370078" ID="ID_426395197" MODIFIED="1717871377438" TEXT="Elemente direkt verschieben"/>
<node CREATED="1717871363090" ID="ID_1350153750" MODIFIED="1717871368574" TEXT="alten Puffer freigeben"/>
</node>
<node CREATED="1717871630138" ID="ID_162586833" MODIFIED="1717871634709" TEXT="Aktions-Logik">
<node CREATED="1717872018862" ID="ID_1125014762" MODIFIED="1717872426247" TEXT="Spread wird nur vergr&#xf6;&#xdf;ert">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
Das ist eine Festlegung aus pragmatischen Gr&#252;nden; weder der Container noch der Builder erfasst den Typ einzelner Elemente, daher gibt es auch keine M&#246;glichkeit, &#252;bersch&#252;ssigen Spread festzustellen. Zwar k&#246;nnte der Client-Code diese Information besitzen, aber dann k&#246;nnte er auch gleich richtig dimensionieren. Generell wird der &#196;nderung des Spread keine besondere Bedeutung zugemessen &#8212; wenn es geht, wird's gemacht.
</p>
</body>
</html>
</richcontent>
<icon BUILTIN="yes"/>
</node>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1717884512847" ID="ID_1565824800" MODIFIED="1717884527086" TEXT="Design-Schwierigkeiten">
<icon BUILTIN="messagebox_warning"/>
<node CREATED="1717873579132" ID="ID_1186499104" MODIFIED="1717873645754" TEXT="M&#xf6;glichkeit dynamischer Gr&#xf6;&#xdf;en-Justierung ist erst auf Allokator-Ebene bekannt">
<icon BUILTIN="messagebox_warning"/>
</node>
<node CREATED="1717873663393" ID="ID_510996186" MODIFIED="1717873700875" TEXT="falls umkopiert werden mu&#xdf;, ist auch noch die Methode zu w&#xe4;hlen (Konstruktor oder memmove)">
<icon BUILTIN="messagebox_warning"/>
</node>
<node CREATED="1717873749393" ID="ID_1296625980" MODIFIED="1717884523389" TEXT="inkrementelle Wahl der Puffergr&#xf6;&#xdf;e ist komplex und zustandsabh&#xe4;ngig">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
der Puffer sollte mit einem Initial-Wert beginnen, und dann in Verdoppelungs-Schriten wachsen; Verdoppelung setzt nat&#252;rlich Kenntnis der aktuellen Puffergr&#246;&#223;e voraus; dabei g&#228;be es aber auch noch einen Maximalwert zu beachten, der vom Allokator abh&#228;ngen kann.
</p>
</body>
</html>
</richcontent>
</node>
</node>
<node CREATED="1717884537799" ID="ID_869921208" MODIFIED="1717884548769" TEXT="die Logik umdrehen">
<icon BUILTIN="idea"/>
<node CREATED="1717884550642" ID="ID_1492766107" MODIFIED="1717884601656" TEXT="wild-copy explizit ausschlie&#xdf;en &#x2014; anstatt es explizit einzuschalten"/>
<node CREATED="1717884707582" ID="ID_1628844564" MODIFIED="1717884772953" TEXT="daf&#xfc;r dann auch die potentiell gef&#xe4;hrlichen Aktionen direkt am Eingang unterbinden"/>
<node CREATED="1717884782596" ID="ID_1264810588" MODIFIED="1717884808660" TEXT="damit kann dann die AllocationPolicy selber entscheiden, was zu tun ist"/>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1717857964116" ID="ID_1398927698" MODIFIED="1717858080950" TEXT="spread-Erweiterung korrekt handhaben">
<linktarget COLOR="#494890" DESTINATION="ID_1398927698" ENDARROW="Default" ENDINCLINATION="-414;28;" ID="Arrow_ID_834912184" SOURCE="ID_1036114720" STARTARROW="None" STARTINCLINATION="389;36;"/>
<icon BUILTIN="yes"/>