Library: enable empty-base optimisation for allocator

...this is an important detail: quite commonly, a custom allocator
is actually implemented as monostate, to avoid bloating every client container
with a backlink pointer; by inheriting the `StdFactory` adapter from the
allocator, the empty-base optimisation can be exploited.

In the standard case thus LinkedElements is the same size as a single
pointer, which is already exploited at several places in the code base.
Notably `AllocationCluster` uses a »virtual overlay« to dress-up the
position pointer as `LinkedElements`, allowing to delegate most of the
administration and memory management to existing and verified code.


With this adjustments, `LinkedElements` pass the tests again
and the rework of `AllocationCluster` is considered complete.
This commit is contained in:
Fischlurch 2024-05-27 19:02:31 +02:00
parent cf80a292c1
commit 178107e8b9
6 changed files with 202 additions and 131 deletions

View file

@ -109,11 +109,14 @@ namespace lib {
};
using Extents = lib::LinkedElements<Extent>;
static_assert (sizeof(Destructors) == sizeof(void*));
static_assert (sizeof(Extents) == sizeof(void*));
union ManagementView
{
Storage storage;
Extents extents;
};
}; //Note: storage.pos and extents.head_ reside at the same location
ManagementView view_;

View file

@ -65,20 +65,6 @@ namespace lib {
class AllocationCluster
: util::MoveOnly
{
template<typename X>
struct Allocator
{
using value_type = X;
[[nodiscard]] X* allocate (size_t n) { return mother_->allot<X>(n); }
void deallocate (X*, size_t) noexcept { /* rejoice */ }
Allocator(AllocationCluster* m) : mother_{m} { }
private:
AllocationCluster* mother_;
};
class StorageManager;
/** maintaining the Allocation */
@ -106,12 +92,9 @@ namespace lib {
AllocationCluster ();
~AllocationCluster () noexcept;
template<typename X>
Allocator<X>
getAllocator()
{
return Allocator<X>{this};
}
/* === diagnostics === */
size_t numExtents() const;
size_t numBytes() const;
template<class TY, typename...ARGS>
@ -121,10 +104,24 @@ namespace lib {
TY& createDisposable (ARGS&& ...);
/* === diagnostics === */
template<typename X>
struct Allocator
{
using value_type = X;
[[nodiscard]] X* allocate (size_t n) { return mother_->allot<X>(n); }
void deallocate (X*, size_t) noexcept { /* rejoice */ }
Allocator(AllocationCluster* m) : mother_{m} { }
// standard copy acceptable
template<typename T>
Allocator(Allocator<T> const& o) : mother_{o.mother_} { }
AllocationCluster* mother_;
};
size_t numExtents() const;
size_t numBytes() const;
template<typename X>
Allocator<X> getAllocator() { return this; }
private:

View file

@ -85,27 +85,31 @@ namespace lib {
* from the given base allocator
* - alternatively, an attempt will be made to default-construct
* the rebound allocator for the other type requested.
* @warn Both avenues for adaptation may fail, which could lead to
* compilation or runtime failures.
* @warning Both avenues for adaptation may fail,
* which could lead to compilation or runtime failure.
* @remark deliberately this class inherits from the allocator,
* allowing to exploit empty-base-optimisation, since
* usage of monostate allocators is quite common.
*/
template<class ALO>
class StdFactory
: private ALO
{
using Allo = ALO;
using AlloT = std::allocator_traits<Allo>;
using BaseType = typename Allo::value_type;
Allo allocator_;
Allo& baseAllocator() { return *this; }
template<typename X>
auto
adaptAllocator (Allo const& baseAllocator)
adaptAllocator()
{
using XAllo = typename AlloT::template rebind_alloc<X>;
if constexpr (std::is_constructible_v<XAllo, Allo>)
return XAllo(allocator_);
return XAllo{baseAllocator()};
else
return XAllo();
return XAllo{};
}
template<class ALOT, typename...ARGS>
@ -139,18 +143,18 @@ namespace lib {
* all those front-end instances exchangeable.
*/
StdFactory (Allo allo = Allo{})
: allocator_{std::move (allo)}
: Allo{std::move (allo)}
{ }
template<class XALO>
bool constexpr operator== (StdFactory<XALO> const& o) const
{
return allocator_ == o.allocator_;
return baseAllocator() == o.baseAllocator();
}
template<class XALO>
bool constexpr operator!= (StdFactory<XALO> const& o) const
{
return not (allocator_ == o.allocator_);
return not (*this == o);
}
@ -161,12 +165,12 @@ namespace lib {
{
if constexpr (std::is_same_v<TY, BaseType>)
{
return construct<AlloT> (allocator_, std::forward<ARGS>(args)...);
return construct<AlloT> (baseAllocator(), std::forward<ARGS>(args)...);
}
else
{
using XAlloT = typename AlloT::template rebind_traits<TY>;
auto xAllo = adaptAllocator<TY> (allocator_);
auto xAllo = adaptAllocator<TY>();
return construct<XAlloT> (xAllo, std::forward<ARGS>(args)...);
}
}
@ -178,12 +182,12 @@ namespace lib {
{
if constexpr (std::is_same_v<TY, BaseType>)
{
destroy<AlloT> (allocator_, elm);
destroy<AlloT> (baseAllocator(), elm);
}
else
{
using XAlloT = typename AlloT::template rebind_traits<TY>;
auto xAllo = adaptAllocator<TY> (allocator_);
auto xAllo = adaptAllocator<TY>();
destroy<XAlloT> (xAllo, elm);
}
}

View file

@ -37,6 +37,9 @@
** - convenient access through Lumiera Forward Iterators
** - the need to integrate tightly with a custom allocator
**
** @note effectively, LinkedElements is just a dressed-up pointer;
** under the assumption that the allocator is a _monostate_, and
** exploiting _empty-base-optimisation,_ footprint is minimal.
** @note this linked list container is _intrusive_ and thus needs the help
** of the element type, which must *provide a pointer member* `next`.
** Consequently, each such node element can not be member in
@ -96,13 +99,14 @@ namespace lib {
using CustomAllocator = ALO;
};
/** default policy: use standard heap allocation for new elements */
template<class N>
using OwningHeapAllocated = OwningAllocated<std::allocator<N>>;
/**
* Policy for LinkedElements: never create or destroy
* any elements, only allow to add already existing nodes.
@ -133,58 +137,7 @@ namespace lib {
} // ... you'll have to do that yourself (that's the whole point of using this strategy)
};
#ifdef LIB_ALLOCATION_CLUSTER_H
/**
* Policy for LinkedElements: especially using a
* lib::AllocationCluster instance for creating
* new node elements. It is mandatory to pass
* this cluster instance to the ctor of any
* LinkedElements list using this policy
* @note AllocationCluster always de-allocates
* any created elements in one sway.
*/
struct UseAllocationCluster
{
typedef AllocationCluster& CustomAllocator;
CustomAllocator cluster_;
explicit
UseAllocationCluster (CustomAllocator clu)
: cluster_(clu)
{ }
/** while this policy indeed implies creating and owing
* new objects, the AllocationCluster doesn't support
* discarding individual instances. All created objects
* within the cluster will be bulk de-allocated
* when the cluster as such goes out of scope.
*/
void
dispose (void*)
{
/* does nothing */
}
template<class TY, typename...ARGS>
TY*
create (ARGS&& ...args)
{
return & cluster_.create<TY> (std::forward<ARGS> (args)...);
}
};
#endif //(End)if lib/allocation-cluster.hpp was included
}//(END)namespace linked_elements
}//(END)namespace linked_elements (predefined policies)
@ -195,7 +148,7 @@ namespace lib {
/**
/****************************************************************************//**
* Intrusive single linked list, possibly taking ownership of node elements.
* Additional elements can be pushed (prepended) to the list; element access
* is per index number (slow) or through an Lumiera Forward Iterator traversing
@ -205,9 +158,10 @@ namespace lib {
* The allocation and ownership related behaviour is controlled by a policy class
* provided as template parameter. When this policy supports creation of new
* elements, these might be created and prepended in one step.
* @note with the default policy, `sizeof(LinkedElements) == sizeof(N*)`
*/
template
< class N ///< node class or Base/Interface class for nodes
< class N ///< node class or Base/Interface class for nodes
, class ALO = linked_elements::OwningHeapAllocated<N>
>
class LinkedElements
@ -218,7 +172,7 @@ namespace lib {
public:
~LinkedElements()
~LinkedElements() noexcept
{
clear();
}
@ -244,7 +198,8 @@ namespace lib {
, head_{nullptr}
{ }
/** creating a LinkedElements list in RAII-style:
/**
* creating a LinkedElements list in RAII-style:
* @param elements iterator to provide all the elements
* to be pushed into this newly created collection
* @note any exception while populating the container
@ -269,7 +224,7 @@ namespace lib {
/** @note EX_FREE */
void
clear()
clear() noexcept
{
while (head_)
{
@ -304,7 +259,7 @@ namespace lib {
*/
template<typename TY>
TY&
push (TY& elm)
push (TY& elm) noexcept
{
elm.next = head_;
head_ = &elm;

View file

@ -28,7 +28,6 @@
#include "lib/test/run.hpp"
#include "lib/test/test-helper.hpp"
#include "lib/test/diagnostic-output.hpp"/////////////TODO
#include "lib/util.hpp"
#include "lib/allocation-cluster.hpp"
@ -158,7 +157,7 @@ namespace test{
return n*(n+1) / 2;
}
}//(End) subversive test data
}//(End) test data and helpers
@ -170,9 +169,6 @@ namespace test{
/// managing existing node elements without taking ownership
using ListNotOwner = LinkedElements<Nummy, linked_elements::NoOwnership>;
/// creating nodes in-place, using a custom allocator for creation and disposal
using ListCustomAllocated = LinkedElements<Nummy, linked_elements::UseAllocationCluster>;
/****************************************************************//**
@ -474,21 +470,56 @@ namespace test{
}
/** Policy to use an Allocation cluster,
* but also to invoke all object destructors */
struct UseAllocationCluster
{
typedef AllocationCluster& CustomAllocator;
CustomAllocator cluster_;
UseAllocationCluster (CustomAllocator clu)
: cluster_(clu)
{ }
template<class TY, typename...ARGS>
TY*
create (ARGS&& ...args)
{
return & cluster_.create<TY> (std::forward<ARGS> (args)...);
}
void dispose (void*) { /* does nothing */ }
};
/** @test use custom allocator to create list elements
* - a dedicated policy allows to refer to an existing AllocationCluster
* and to arrange for all object destructors to be called when this
* cluster goes out of scope
* - a C++ standard allocator can also be used; as an example, again an
* AllocationCluster is used, but this time with the default adapter,
* which places objects tight and skips invocation of destructors;
* however, since the LinkedElements destructor is called, it
* walks all elements and delegates through std::allocator_traits,
* which will invoke the (virtual) base class destructors.
*/
void
verify_customAllocator()
{
CHECK (0 == Dummy::checksum());
{
AllocationCluster allocator;
AllocationCluster cluster;
ListCustomAllocated elements(allocator);
LinkedElements<Nummy, UseAllocationCluster> elements(cluster);
elements.emplace<Num<1>> (2);
elements.emplace<Num<3>> (4,5);
elements.emplace<Num<6>> (7,8,9);
const size_t EXPECT = sizeof(Num<1>) + sizeof(Num<3>) + sizeof(Num<6>) + 3*2*sizeof(void*);
CHECK (EXPECT == allocator.numBytes());
const size_t EXPECT = sizeof(Num<1>) + sizeof(Num<3>) + sizeof(Num<6>)
+ 3*2*sizeof(void*); // ◁┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄overhead for storing 3 dtor-invokers
CHECK (EXPECT == cluster.numBytes());
CHECK (sum(9) == Dummy::checksum());
CHECK (3 == elements.size());
@ -497,13 +528,34 @@ namespace test{
CHECK (6+7+8+9 == elements[0].getVal());
elements.clear();
CHECK (EXPECT == allocator.numBytes());
CHECK (EXPECT == cluster.numBytes());
CHECK (sum(9) == Dummy::checksum());
// note: elements won't be discarded unless
// the AllocationCluster goes out of scope
SHOW_EXPR(Dummy::checksum())
}
SHOW_EXPR(Dummy::checksum())
CHECK (0 == Dummy::checksum());
{
// now use AllocationCluster through the default allocator adapter...
AllocationCluster cluster;
using Allo = AllocationCluster::Allocator<Nummy>;
using Elms = LinkedElements<Nummy, linked_elements::OwningAllocated<Allo>>;
Elms elements{cluster.getAllocator<Nummy>()};
elements.emplace<Num<1>> (2);
elements.emplace<Num<3>> (4,5);
const size_t EXPECT = sizeof(Num<1>) + sizeof(Num<3>);
CHECK (EXPECT == cluster.numBytes());
CHECK (sum(5) == Dummy::checksum());
CHECK (2 == elements.size());
CHECK (1+2 == elements[1].getVal());
CHECK (3+4+5 == elements[0].getVal());
// note: this time the destructors will be invoked
// from LinkedElements::clear(), but not from
// the destructor of AllocationCluster
}
CHECK (0 == Dummy::checksum());
}
};

View file

@ -65106,9 +65106,9 @@
<node COLOR="#338800" CREATED="1686696718121" ID="ID_1035772269" MODIFIED="1686696767814" TEXT="vorl&#xe4;ufig implementiert durch std::list mit Inline-Buffer">
<icon BUILTIN="button_ok"/>
</node>
<node BACKGROUND_COLOR="#d2beaf" COLOR="#5c4d6e" CREATED="1686696768847" ID="ID_48162464" MODIFIED="1716683834965" TEXT="das gleiche Aufruf-Pattern in AllocationCluster integrieren">
<arrowlink COLOR="#515b9a" DESTINATION="ID_910814489" ENDARROW="Default" ENDINCLINATION="167;-10;" ID="Arrow_ID_96021000" STARTARROW="None" STARTINCLINATION="168;8;"/>
<icon BUILTIN="hourglass"/>
<node COLOR="#5b280f" CREATED="1686696768847" ID="ID_48162464" MODIFIED="1716828253252" TEXT="das gleiche Aufruf-Pattern in AllocationCluster integrieren">
<arrowlink COLOR="#517f9a" DESTINATION="ID_910814489" ENDARROW="Default" ENDINCLINATION="167;-10;" ID="Arrow_ID_96021000" STARTARROW="None" STARTINCLINATION="168;8;"/>
<icon BUILTIN="button_cancel"/>
</node>
</node>
<node BACKGROUND_COLOR="#f8f1cb" COLOR="#a50125" CREATED="1716677970109" ID="ID_282740712" MODIFIED="1716677984988" TEXT="Konflikt &#x2016; Design-Ziele nicht klar">
@ -65172,19 +65172,56 @@
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1716683768504" ID="ID_1462693245" MODIFIED="1716683781871" TEXT="Draft / Prototyping">
<linktarget COLOR="#943871" DESTINATION="ID_1462693245" ENDARROW="Default" ENDINCLINATION="-1171;2688;" ID="Arrow_ID_230796845" SOURCE="ID_158782942" STARTARROW="None" STARTINCLINATION="-815;-23;"/>
<icon BUILTIN="pencil"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1716683783293" ID="ID_910814489" MODIFIED="1716683827701" TEXT="Standard-Allocator in LinkedElements integrieren">
<linktarget COLOR="#515b9a" DESTINATION="ID_910814489" ENDARROW="Default" ENDINCLINATION="167;-10;" ID="Arrow_ID_96021000" SOURCE="ID_48162464" STARTARROW="None" STARTINCLINATION="168;8;"/>
<icon BUILTIN="flag-yellow"/>
<node COLOR="#338800" CREATED="1716683783293" ID="ID_910814489" MODIFIED="1716828248548" TEXT="Standard-Allocator in LinkedElements integrieren">
<linktarget COLOR="#517f9a" DESTINATION="ID_910814489" ENDARROW="Default" ENDINCLINATION="167;-10;" ID="Arrow_ID_96021000" SOURCE="ID_48162464" STARTARROW="None" STARTINCLINATION="168;8;"/>
<icon BUILTIN="button_ok"/>
<node COLOR="#338800" CREATED="1716743917838" ID="ID_1038539692" MODIFIED="1716743966300" TEXT="Entwurf: StdFactory (Adapter)">
<icon BUILTIN="button_ok"/>
<node CREATED="1716769836348" ID="ID_323593289" MODIFIED="1716769873715" TEXT="private Adapter-Funktionen und den Allokator in ein privates Feld"/>
<node COLOR="#435e98" CREATED="1716769874254" ID="ID_1245762585" MODIFIED="1716822400050" TEXT="lie&#xdf;e sich der Allokator als Basisklasse anordnen?">
<linktarget COLOR="#e7053e" DESTINATION="ID_1245762585" ENDARROW="Default" ENDINCLINATION="16;46;" ID="Arrow_ID_316103810" SOURCE="ID_221563395" STARTARROW="None" STARTINCLINATION="-49;-3;"/>
<icon BUILTIN="help"/>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#a6278d" CREATED="1716769956164" ID="ID_1434540712" MODIFIED="1716769975843" TEXT="puh... das wird h&#xe4;sslich">
<icon BUILTIN="smiley-angry"/>
</node>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1716769978195" ID="ID_660104995" MODIFIED="1716822397747" TEXT="EBO ist aber ein wichtiger Belang hier">
<icon BUILTIN="yes"/>
</node>
<node COLOR="#435e98" CREATED="1716822372753" ID="ID_1585783821" MODIFIED="1716822393513" TEXT="mit einer casting-Hilfsfunktion bekommt man es einigerma&#xdf;en lesbar">
<icon BUILTIN="idea"/>
</node>
<node COLOR="#338800" CREATED="1716822385027" ID="ID_1753587284" MODIFIED="1716822390899" TEXT="erkl&#xe4;render Kommentar dazu">
<icon BUILTIN="button_ok"/>
</node>
</node>
</node>
<node COLOR="#338800" CREATED="1716743934765" ID="ID_472100312" MODIFIED="1716767998222" TEXT="Policy OwningHeapAllocated re-implementieren auf Basis von StdFactory">
<icon BUILTIN="button_ok"/>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1716769724137" ID="ID_221563395" MODIFIED="1716822406633" TEXT="Problem: empty-base-optimisation greift nicht mehr">
<arrowlink COLOR="#e7053e" DESTINATION="ID_1245762585" ENDARROW="Default" ENDINCLINATION="16;46;" ID="Arrow_ID_316103810" STARTARROW="None" STARTINCLINATION="-49;-3;"/>
<icon BUILTIN="broken-line"/>
<node CREATED="1716769752783" ID="ID_143245631" MODIFIED="1716769760514" TEXT="der Adapter hat ein Feld allocator_"/>
<node CREATED="1716769776693" ID="ID_1419342319" MODIFIED="1716822425789">
<richcontent TYPE="NODE"><html>
<head/>
<body>
<p>
&#10233; LinkedElements ist nicht mehr kongruent
</p>
<p>
&#160;&#160;&#160;&#160;&#160;&#160;mit einem einfachen Pointer
</p>
</body>
</html></richcontent>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1716683843917" ID="ID_157117808" MODIFIED="1716684087738" TEXT="Standard-Allocator f&#xfc;r AllocationCluster bereitstellen">
<linktarget COLOR="#664940" DESTINATION="ID_157117808" ENDARROW="Default" ENDINCLINATION="1249;67;" ID="Arrow_ID_572544135" SOURCE="ID_1456163487" STARTARROW="None" STARTINCLINATION="131;-1027;"/>
<icon BUILTIN="flag-yellow"/>
<node CREATED="1716822440964" ID="ID_214165023" MODIFIED="1716822473804" TEXT="StdFactory auf EBO umgestellt &#x27f9; funktioniert mit std::allocator"/>
</node>
<node CREATED="1716822489293" ID="ID_181197177" MODIFIED="1716822501360" TEXT="die spezielle Policy f&#xfc;r AllocationCluster wird damit hinf&#xe4;llig"/>
</node>
<node COLOR="#338800" CREATED="1716683843917" ID="ID_157117808" MODIFIED="1716828259250" TEXT="Standard-Allocator f&#xfc;r AllocationCluster bereitstellen">
<linktarget COLOR="#404f66" DESTINATION="ID_157117808" ENDARROW="Default" ENDINCLINATION="1249;67;" ID="Arrow_ID_572544135" SOURCE="ID_1456163487" STARTARROW="None" STARTINCLINATION="131;-1027;"/>
<icon BUILTIN="button_ok"/>
</node>
</node>
</node>
@ -81862,10 +81899,13 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</node>
<node COLOR="#338800" CREATED="1715725787852" ID="ID_1127426666" MODIFIED="1715729452446" TEXT="neues einfacheres Interface einbauen">
<icon BUILTIN="button_ok"/>
<node BACKGROUND_COLOR="#f8f1cb" COLOR="#a50125" CREATED="1715726296833" ID="ID_320488527" MODIFIED="1715726378902" TEXT="Problem: einzel-Allocator pro Typ">
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1715726296833" ID="ID_320488527" MODIFIED="1716828384070" TEXT="Problem: einzel-Allocator pro Typ">
<icon BUILTIN="messagebox_warning"/>
<node CREATED="1715726380325" ID="ID_810607124" MODIFIED="1715726397415" TEXT="f&#xfc;hrt zu hierarchischer Struktur"/>
<node CREATED="1715726517963" ID="ID_1603078940" MODIFIED="1715726538868" TEXT="als nested class mit Zugang zu privaten Methoden"/>
<node CREATED="1716828352153" ID="ID_1078249129" MODIFIED="1716828378896" TEXT="quer-Konstruierbarkeit als spezielle Erweierung f&#xfc;r unsere StdFactory">
<icon BUILTIN="idea"/>
</node>
</node>
<node CREATED="1715727163500" ID="ID_164792121" MODIFIED="1715727175958" TEXT="API">
<node CREATED="1715727225764" ID="ID_123722889" MODIFIED="1715727230671" TEXT="getAllocator&lt;TY&gt;"/>
@ -81877,22 +81917,22 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</node>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1715782501810" ID="ID_455348105" MODIFIED="1715782506785" TEXT="Verwendungen anpassen">
<icon BUILTIN="pencil"/>
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1715782508685" ID="ID_524633561" MODIFIED="1715782536584" TEXT="AllocationCluster selber mu&#xdf; weiterhin default-constructible sein">
<node COLOR="#435e98" CREATED="1715782508685" ID="ID_524633561" MODIFIED="1716828337676" TEXT="AllocationCluster selber mu&#xdf; weiterhin default-constructible sein">
<icon BUILTIN="yes"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1715782580806" ID="ID_1223928211" MODIFIED="1715782592605" TEXT="tats&#xe4;chliche Objekt-Erzeugungen nachvollziehen...">
<icon BUILTIN="flag-yellow"/>
<node CREATED="1715782747520" ID="ID_1770179360" MODIFIED="1715782759542" TEXT="node-basic-test: OK"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1715782790810" ID="ID_1391251855" MODIFIED="1715782799529" TEXT="linked-elements-test: ">
<icon BUILTIN="flag-yellow"/>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1715815439855" ID="ID_1456163487" MODIFIED="1716684137464" TEXT="sollte LinkedElements umstellen auf Standard-konformen Allocator">
<arrowlink COLOR="#664940" DESTINATION="ID_157117808" ENDARROW="Default" ENDINCLINATION="1249;67;" ID="Arrow_ID_572544135" STARTARROW="None" STARTINCLINATION="131;-1027;"/>
<icon BUILTIN="pencil"/>
<node COLOR="#338800" CREATED="1715782790810" ID="ID_1391251855" MODIFIED="1716828317465" TEXT="linked-elements-test">
<icon BUILTIN="button_ok"/>
<node COLOR="#338800" CREATED="1715815439855" ID="ID_1456163487" MODIFIED="1716828291983" TEXT="LinkedElements umstellen auf Standard-konformen Allocator">
<arrowlink COLOR="#404f66" DESTINATION="ID_157117808" ENDARROW="Default" ENDINCLINATION="1249;67;" ID="Arrow_ID_572544135" STARTARROW="None" STARTINCLINATION="131;-1027;"/>
<icon BUILTIN="button_ok"/>
<node CREATED="1716684095508" ID="ID_1857326363" MODIFIED="1716684131661" TEXT="der mu&#xdf; dann die default-Policy ersetzen">
<icon BUILTIN="yes"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1716684105741" ID="ID_1677827906" MODIFIED="1716684129032" TEXT="also: Ownership + gegebenen Standard-Allocator als Schnittstelle">
<icon BUILTIN="flag-yellow"/>
<node COLOR="#338800" CREATED="1716684105741" ID="ID_1677827906" MODIFIED="1716828275075" TEXT="also: Ownership + gegebenen Standard-Allocator als Schnittstelle">
<icon BUILTIN="button_ok"/>
</node>
</node>
<node CREATED="1715815513228" ID="ID_1909349257" MODIFIED="1715815549523" TEXT="die NoOwnership-Policy wird dann zu einem speziellen Allocator"/>
@ -81944,8 +81984,8 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<node CREATED="1715819206460" ID="ID_897739837" MODIFIED="1715819231318" TEXT="mu&#xdf; jedweils im aktuellen Block den Rest-Speicher feststellen k&#xf6;nnen"/>
<node CREATED="1715819263910" ID="ID_1512700101" MODIFIED="1715819291686" TEXT="soll idealerweise auch noch die Destructor-Closures mit unterbringen"/>
</node>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1715819352242" ID="ID_1754180627" MODIFIED="1715820238650" TEXT="Implementierung">
<icon BUILTIN="pencil"/>
<node COLOR="#338800" CREATED="1715819352242" FOLDED="true" ID="ID_1754180627" MODIFIED="1716828681835" TEXT="Implementierung">
<icon BUILTIN="button_ok"/>
<node CREATED="1715820246484" ID="ID_232038748" MODIFIED="1715820255249" TEXT="Idee / Skizze">
<icon BUILTIN="idea"/>
<node CREATED="1715819500198" ID="ID_210469417" MODIFIED="1715819513137" TEXT="ein Paar (next*, remaining_size)">
@ -82121,7 +82161,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1716130730820" ID="ID_539013579" MODIFIED="1716130744964" TEXT="ich mache hier gef&#xe4;hrliche Sachen">
<icon BUILTIN="clanbomber"/>
</node>
<node BACKGROUND_COLOR="#c8c0b6" COLOR="#435e98" CREATED="1716130764415" ID="ID_966285930" MODIFIED="1716657861262" TEXT="explizit zu verifizieren">
<node BACKGROUND_COLOR="#c8c0b6" COLOR="#435e98" CREATED="1716130764415" ID="ID_966285930" MODIFIED="1716828421762" TEXT="explizit zu verifizieren">
<icon BUILTIN="yes"/>
<node COLOR="#338800" CREATED="1716130773434" ID="ID_643589646" MODIFIED="1716657856744" TEXT="Destruktoren werden aufgerufen &#x27f9; Pr&#xfc;fsumme">
<icon BUILTIN="button_ok"/>
@ -82133,6 +82173,26 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<icon BUILTIN="button_ok"/>
</node>
</node>
<node COLOR="#338800" CREATED="1716828422424" ID="ID_255250462" MODIFIED="1716828445335" TEXT="den gesamten Konstruktions / Destruktions-Ablauf im Debugger nachvollzogen">
<icon BUILTIN="button_ok"/>
</node>
<node COLOR="#338800" CREATED="1716828448665" ID="ID_696174319" MODIFIED="1716828458676" TEXT="static-assertions f&#xfc;r den Layout-Constraint">
<icon BUILTIN="button_ok"/>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1716828459932" HGAP="23" ID="ID_265585252" LINK="#ID_221563395" MODIFIED="1716828628769" TEXT="aus gutem Grund...." VSHIFT="2">
<richcontent TYPE="NOTE"><html>
<head/>
<body>
<p>
beim Umbau der Policy f&#252;r LinkedElements habe ich zun&#228;chst einen Adapter geschrieben, der den std::allocator sch&#246;n sauber als Member h&#228;lt &#8212; nur wird dadurch dann sizeof(LinkedElements) &#8801; 2 &#187;slots&#171;. Und damit kippt der ganze Layout-Trick weg und der Destruktor l&#228;uft Amok.
</p>
<p>
&#160;&#160;&#160;<i>Lessions Learned</i>
</p>
</body>
</html></richcontent>
<font NAME="SansSerif" SIZE="11"/>
</node>
</node>
<node COLOR="#338800" CREATED="1716130832134" ID="ID_1783945506" MODIFIED="1716133346231" TEXT="hierf&#xfc;r einen friend-Test schaffen">
<linktarget COLOR="#4173be" DESTINATION="ID_1783945506" ENDARROW="Default" ENDINCLINATION="204;17;" ID="Arrow_ID_1547348126" SOURCE="ID_253325898" STARTARROW="None" STARTINCLINATION="292;-22;"/>
<icon BUILTIN="button_ok"/>
@ -82141,7 +82201,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</node>
</node>
<node COLOR="#338800" CREATED="1715790315814" ID="ID_878890004" MODIFIED="1716659839834" TEXT="L&#xf6;sung f&#xfc;r die Destruktoren schaffen">
<linktarget COLOR="#af578d" DESTINATION="ID_878890004" ENDARROW="Default" ENDINCLINATION="-446;33;" ID="Arrow_ID_464677545" SOURCE="ID_412040509" STARTARROW="None" STARTINCLINATION="-568;-24;"/>
<linktarget COLOR="#57a3af" DESTINATION="ID_878890004" ENDARROW="Default" ENDINCLINATION="-446;33;" ID="Arrow_ID_464677545" SOURCE="ID_412040509" STARTARROW="None" STARTINCLINATION="-568;-24;"/>
<icon BUILTIN="button_ok"/>
<node CREATED="1715790397014" ID="ID_14966020" LINK="#ID_869337683" MODIFIED="1715790537195" TEXT="Ergebnis einer Konfliktl&#xf6;sung">
<richcontent TYPE="NOTE"><html>
@ -82547,7 +82607,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<node CREATED="1715790137116" ID="ID_609184098" MODIFIED="1715790158047" TEXT="es wird explizit eine Registrierung f&#xfc;r clean-up vorgesehen"/>
<node CREATED="1715790158683" ID="ID_863625795" MODIFIED="1715790174701" TEXT="diese bleibt aber getrennt vom eigentlichen Allokations-Management"/>
<node CREATED="1715790293402" ID="ID_412040509" MODIFIED="1715790393998" TEXT="sie wird per convenience-Shortcut an den Allocation-Cluster gebunden">
<arrowlink COLOR="#af578d" DESTINATION="ID_878890004" ENDARROW="Default" ENDINCLINATION="-446;33;" ID="Arrow_ID_464677545" STARTARROW="None" STARTINCLINATION="-568;-24;"/>
<arrowlink COLOR="#57a3af" DESTINATION="ID_878890004" ENDARROW="Default" ENDINCLINATION="-446;33;" ID="Arrow_ID_464677545" STARTARROW="None" STARTINCLINATION="-568;-24;"/>
</node>
</node>
</node>