diff --git a/src/lib/several-builder.hpp b/src/lib/several-builder.hpp index 3b2401a8f..61867a8c2 100644 --- a/src/lib/several-builder.hpp +++ b/src/lib/several-builder.hpp @@ -47,6 +47,7 @@ #include "lib/iter-explorer.hpp" #include "lib/util.hpp" +#include #include #include #include @@ -69,13 +70,59 @@ namespace lib { UNIMPLEMENTED ("adjust memory allocation"); ///////////////////////////OOO Problem Objekte verschieben } }; + + using std::is_trivially_move_constructible_v; + using std::is_trivially_destructible_v; + using std::has_virtual_destructor_v; + using std::is_same_v; + using lib::meta::is_Subclass; + + template + struct MemStrategy + { + bool disposable :1 ; + bool wild_move :1 ; + + template + bool + canDestroy() + { + return disposable + or (is_trivially_destructible_v and is_trivially_destructible_v) + or (has_virtual_destructor_v and is_Subclass()) + or (is_same_v and is_Subclass()); + } + + template + bool + canDynGrow() + { + return is_same_v + or (is_trivially_move_constructible_v and wild_move); + } + + auto + getDeleter() + { + if constexpr (disposable or + (is_trivially_destructible_v and is_trivially_destructible_v)) + return nullptr; + if constexpr (has_virtual_destructor_v) + return nullptr; + else + return nullptr; + } + }; } /** * Wrap a vector holding objects of a subtype and * provide array-like access using the interface type. */ - template + template + ,class E =I ///< a subclass element element type (relevant when not trivially movable and destructible) + ,class POL =HeapOwn ///< Allocator policy + > class SeveralBuilder : Several , POL @@ -121,7 +168,7 @@ namespace lib { adjustStorage (size_t cnt, size_t spread) { if (cnt*spread > storageSiz_) - {// need more storage.. + { // need more storage... Col::data_ = static_cast (POL::realloc (Col::data_, storageSiz_, cnt*spread)); storageSiz_ = cnt*spread; } @@ -130,7 +177,7 @@ namespace lib { adjustSpread (spread); if (cnt*spread < storageSiz_) - {// attempt to shrink storage + { // attempt to shrink storage Col::data_ = static_cast (POL::realloc (Col::data_, storageSiz_, cnt*spread)); storageSiz_ = cnt*spread; } diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index 59ea1f6b8..57253f371 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -81444,16 +81444,13 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - - +

...man verwendet nur speziell im produktiven Einsatz im Node-Graph  einen besonderen Allocator, der zwar den Destruktor aufruft, aber den Speicher nicht freigibt; alloziert wird immer in einen kompakten Block hinein, der dann auf der Basis der Prozeß-Kenntnis als Ganzes verworfen und neu verwendet wird.

- -
+
@@ -81680,16 +81677,13 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - - +

Konsequenz: man kann einen einzigen Typ Several<X> anschreiben

- -
+
@@ -81750,42 +81744,33 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - - +

...und zwar vor allem durch den AllocationCluster mit einer festen Extent-Size. Vorhersehbar werden die Extents meist zu groß sein...

- -
+
- - - +

...und was noch besser ist: die Storage liegt kompakt

- -
+
- - - +

...weil wir durch den Connectivity-Descriptor bereits eine gefährlich komplexes Stück Metaprogramming haben, mit dem Risiko kombinatorischer Explosion

- -
+
@@ -81820,16 +81805,13 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - - +

diese Funktion würde eine Exception werfen, wen das ArrayBucket eben doch ownership-managed ist. Ansonsten erzeugt sie eine neue Instanz mit Verweis auf das gemeinsam nutzbare Bucket

- -
+
@@ -81851,16 +81833,13 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - - +

...weil ich den Zieltyp zum Cast nicht dynamisch konstruieren kann

- -
+
@@ -81885,8 +81864,224 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + + + + + + + + + + + + + + + + + + + + + + + + + + +

+ Same as std::move unless the type's move constructor could throw and the type is copyable, in which case an lvalue-reference is returned instead. +

+ +
+ +
+ + + + +

+ __and_<__not_<is_nothrow_move_constructible<_Tp>> +

+

+       , is_copy_constructible<_Tp>> +

+ +
+ + + + + + + + + + + + + + + + + + + + + + +

+ sonst: _M_realloc_insert +

+ +
+ + + + + + + + + + + + + + + + +

+ die C-Funktion realloc() kann zwar scheinbar „zaubern“, ist aber tatsächlich auf Hilfe vom Allokator angewiesen, insofern dieser sich intern gewisse zusätzliche Reserven sichert. Und wenn seine Resevern nicht reichen, dann wird sofort woanders alloziert und alles per memmove()  umkopiert.... +

+ + +
+
+ + + + +

+ Tatsächlich kann std::vector() dasselbe besser machen, da er ggfs move-Konstruktoren aufrufen und außerdem als zusätzliche Heuristik die aktuelle Größe des Vektors heranziehen kann, um eine angemessene Reserve bereitzustellen; außerdem ist die Größe der Reserve direkt auf das API herausgeführt. +

+ + +
+
+ + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +