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:
parent
446f133c09
commit
3a263c8c63
2 changed files with 83 additions and 44 deletions
|
|
@ -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()));
|
||||
|
|
|
|||
|
|
@ -82598,6 +82598,61 @@ Date:   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ä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öße"/>
|
||||
<node CREATED="1717871230816" ID="ID_1183913040" MODIFIED="1717871323010" TEXT="bestehenden Puffer in der Größ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 ⟶ 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ößert">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
Das ist eine Festlegung aus pragmatischen Gründen; weder der Container noch der Builder erfasst den Typ einzelner Elemente, daher gibt es auch keine Möglichkeit, überschüssigen Spread festzustellen. Zwar könnte der Client-Code diese Information besitzen, aber dann könnte er auch gleich richtig dimensionieren. Generell wird der Änderung des Spread keine besondere Bedeutung zugemessen — 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öglichkeit dynamischer Größ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ß, ist auch noch die Methode zu wählen (Konstruktor oder memmove)">
|
||||
<icon BUILTIN="messagebox_warning"/>
|
||||
</node>
|
||||
<node CREATED="1717873749393" ID="ID_1296625980" MODIFIED="1717884523389" TEXT="inkrementelle Wahl der Puffergröße ist komplex und zustandsabhä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ürlich Kenntnis der aktuellen Puffergröße voraus; dabei gäbe es aber auch noch einen Maximalwert zu beachten, der vom Allokator abhä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ßen — anstatt es explizit einzuschalten"/>
|
||||
<node CREATED="1717884707582" ID="ID_1628844564" MODIFIED="1717884772953" TEXT="dafür dann auch die potentiell gefä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"/>
|
||||
|
|
|
|||
Loading…
Reference in a new issue