Library: better handle the alignment issues explicitly

While there might be the possibility to use the magic of the standard library,
it seems prudent rather to handle this insidious problem explicitly,
to make clear what is going on here.

To allow for such explicit alignment handling, I have now changed the
scheme of the storage definition; the actual buffer now starts ''behind''
the `ArrayBucket<I>` object, which thereby becomes a metadata managing header.

__To summarise the problem__: since we are maintaining a dynamically sized buffer,
and since we do not want to expose the actual element type through the
front-end object, we're necessarily bound to perform a raw-memory allocation.
This is denoted in bytes, and thus the allocator can no longer manage
the proper alignment automatically. Rather, we get a storage buffer with
just ''some accidental'' alignment, and we must care to request a sufficient
overhead to be able to shift the actual storage area forward to the next
proper alignment boundary. Obviously this also implies that we must
store this individual padding adjustment somewhere in the metadata,
in order to be able to report the correct size of the block later
on de-allocation.
This commit is contained in:
Fischlurch 2024-06-18 01:15:50 +02:00
parent dc6c8e0858
commit 09c8c2a29f
4 changed files with 189 additions and 104 deletions

View file

@ -41,7 +41,15 @@
** Since the actual data elements can (optionally) be of a different type than
** the exposed interface type \a I, additional storage and spacing is required
** in the element array. The field ArrayBucket<I>::spread defines this spacing
** and thus the offset used for subscript access.
** and thus the offset used for subscript access. The actual data storage starts
** immediately behind the ArrayBucket, which thus acts as a metadata header.
** This arrangement requires a sufficiently sized raw memory allocation to place
** the ArrayBucket and the actual data into. Moreover, the allocation code in
** ElementFactory::create() is responsible to ensure proper alignment of the
** data storage, especially when the payload data type has alignment requirements
** beyond `alignof(void*)`, which is typically used by the standard heap allocator;
** additional headroom is added proactively in this case, to be able to shift the
** storage buffer ahead to the next alignment boundrary.
**
** # Handling of data elements
**
@ -144,9 +152,6 @@ namespace lib {
/**
* Helper to determine the »spread« required to hold
* elements of type \a TY in memory _with proper alignment._
* @warning assumes that the start of the buffer is also suitably aligned,
* which _may not be the case_ for **over-aligned objects** with
* `alignof(TY) > alignof(void*)`
*/
template<typename TY>
size_t inline constexpr
@ -187,16 +192,30 @@ namespace lib {
: Allo{std::move (allo)}
{ }
Bucket*
create (size_t cnt, size_t spread)
create (size_t cnt, size_t spread, size_t alignment =alignof(I))
{
size_t storageBytes = Bucket::requiredStorage (cnt, spread);
REQUIRE (cnt);
REQUIRE (spread);
size_t storageBytes = Bucket::storageOffset + cnt*spread;
if (alignment > alignof(void*)) // over-aligned data => reserve for alignment padding
storageBytes += (alignment - alignof(void*));
// Step-1 : acquire the raw storage buffer
std::byte* loc = AlloT::allocate (baseAllocator(), storageBytes);
ENSURE (0 == size_t(loc) % alignof(void*));
size_t offset = (size_t(loc) + Bucket::storageOffset) % alignment;
if (offset) // padding needed to next aligned location
offset = alignment - offset;
offset += Bucket::storageOffset;
ASSERT (storageBytes - offset >= cnt*spread);
Bucket* bucket = reinterpret_cast<Bucket*> (loc);
using BucketAlloT = typename AlloT::template rebind_traits<Bucket>;
auto bucketAllo = adaptAllocator<Bucket>();
try { BucketAlloT::construct (bucketAllo, bucket, cnt*spread, spread); }
// Step-2 : construct the Bucket metadata | ▽ ArrayBucket ctor arg ▽
try { BucketAlloT::construct (bucketAllo, bucket, storageBytes, offset, spread); }
catch(...)
{
AlloT::deallocate (baseAllocator(), loc, storageBytes);
@ -205,6 +224,7 @@ namespace lib {
return bucket;
};
template<class E, typename...ARGS>
E&
createAt (Bucket* bucket, size_t idx, ARGS&& ...args)
@ -218,6 +238,7 @@ namespace lib {
return *loc;
};
template<class E>
void
destroy (ArrayBucket<I>* bucket)
@ -234,7 +255,7 @@ namespace lib {
ElmAlloT::destroy (elmAllo, elm);
}
}
size_t storageBytes = Bucket::requiredStorage (bucket->buffSiz);
size_t storageBytes = bucket->buffOffset + bucket->buffSiz;
std::byte* loc = reinterpret_cast<std::byte*> (bucket);
AlloT::deallocate (baseAllocator(), loc, storageBytes);
};
@ -255,7 +276,7 @@ namespace lib {
Bucket*
realloc (Bucket* data, size_t cnt, size_t spread)
{
Bucket* newBucket = Fac::create (cnt, spread);
Bucket* newBucket = Fac::create (cnt, spread, alignof(E));
if (data)
try {
newBucket->deleter = data->deleter;
@ -558,7 +579,7 @@ namespace lib {
REQUIRE (oldSpread);
REQUIRE (newSpread);
REQUIRE (Coll::data_);
byte* oldPos = Coll::data_->storage;
byte* oldPos = Coll::data_->storage();
byte* newPos = oldPos;
oldPos += idx * oldSpread;
newPos += idx * newSpread;

View file

@ -71,15 +71,21 @@
namespace lib {
namespace {// Storage implementation details
namespace {// Storage header implementation details
template<class I, class E =I, size_t space = sizeof(I)>
/**
* Metadata record placed immediately before the data storage.
* @remark SeveralBuilder uses a custom allocation scheme to acquire
* a sufficiently sized allocation for ArrayBucket + the data.
*/
template<class I>
struct ArrayBucket
{
ArrayBucket (size_t bytes, size_t elmSize = sizeof(I))
ArrayBucket (size_t storageSize, size_t buffStart, size_t elmSize = sizeof(I))
: cnt{0}
, spread{elmSize}
, buffSiz{bytes}
, buffSiz{storageSize - buffStart}
, buffOffset{buffStart}
, deleter{nullptr}
{ }
@ -88,30 +94,24 @@ namespace lib {
size_t cnt;
size_t spread;
size_t buffSiz;
size_t buffOffset;
Deleter deleter;
/** mark start of the storage area */
alignas(E)
std::byte storage[space];
static constexpr size_t storageOffset = sizeof(ArrayBucket);
static size_t
requiredStorage (size_t cnt, size_t spread =1)
/** data storage area starts immediately behind the ArrayBucket */
std::byte*
storage()
{
return sizeof(ArrayBucket) - sizeof(storage)
+ cnt * spread;
return reinterpret_cast<std::byte*>(this) + buffOffset;
}
/** perform unchecked access into the storage area
* @note typically reaching behind the nominal end of this object
*/
/** perform unchecked access into the storage area */
I&
subscript (size_t idx)
{
std::byte* elm = storage;
size_t off = idx * spread;
elm += off;
ENSURE (storage <= elm and elm < storage+buffSiz);
std::byte* elm = storage() + (idx * spread);
ENSURE (storage() <= elm and elm < storage()+buffSiz);
return * std::launder (reinterpret_cast<I*> (elm));
}

View file

@ -506,29 +506,9 @@ namespace test{
{ // Scenario-2 : alignment
struct Ali
{
alignas(32)
alignas(64)
char charm = 'u';
};
SHOW_EXPR(sizeof(Ali))
SHOW_EXPR(alignof(Ali))
SHOW_EXPR(sizeof(ArrayBucket<Ali>))
SHOW_EXPR(alignof(ArrayBucket<Ali>))
SHOW_EXPR(sizeof(ArrayBucket<Ali, Ali, 10>))
SHOW_EXPR(alignof(ArrayBucket<Ali, Ali, 10>))
SHOW_EXPR(sizeof(ArrayBucket<char, Ali, 10>))
SHOW_EXPR(alignof(ArrayBucket<char, Ali, 10>))
std::allocator<ArrayBucket<Ali>> aliAllo;
std::allocator<std::byte> byteAllo;
ArrayBucket<Ali> * locAli = aliAllo.allocate(1);
std::byte* locByte = byteAllo.allocate(96);
SHOW_EXPR(loc(locAli))
SHOW_EXPR(loc(locAli) % alignof(Ali))
SHOW_EXPR(loc(locByte))
SHOW_EXPR(loc(locByte) % alignof(Ali))
aliAllo.destroy(locAli);
byteAllo.destroy(locByte);
auto elms = makeSeveral<Ali>().fillElm(5).build();
CHECK (5 == elms.size());

View file

@ -81799,7 +81799,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<icon BUILTIN="idea"/>
</node>
</node>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#4e3b7f" CREATED="1718034857705" ID="ID_725324060" MODIFIED="1718586182698" TEXT="Alignment beachten">
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#4e3b7f" CREATED="1718034857705" FOLDED="true" ID="ID_725324060" MODIFIED="1718670952346" TEXT="Alignment beachten">
<icon BUILTIN="messagebox_warning"/>
<node CREATED="1718035817292" ID="ID_908227037" MODIFIED="1718035826853" TEXT="Verwendungen von sizeof(TY)">
<icon BUILTIN="idea"/>
@ -81884,8 +81884,8 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<icon BUILTIN="yes"/>
</node>
</node>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1718066378097" ID="ID_1766969093" MODIFIED="1718588133769" TEXT="Anpassungen am Code">
<icon BUILTIN="pencil"/>
<node COLOR="#338800" CREATED="1718066378097" ID="ID_1766969093" MODIFIED="1718670765224" TEXT="Anpassungen am Code">
<icon BUILTIN="button_ok"/>
<node COLOR="#338800" CREATED="1718066394480" ID="ID_326301567" MODIFIED="1718067158583" TEXT="Puffer-Alignment &#x27f6; void*">
<icon BUILTIN="button_ok"/>
</node>
@ -81895,76 +81895,72 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<node COLOR="#338800" CREATED="1718067163803" ID="ID_1053644006" MODIFIED="1718067198266" TEXT="&quot;sizeof(TY)&quot; &#x27fc; reqSiz&lt;TY&gt;()">
<icon BUILTIN="button_ok"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1718586230120" ID="ID_1182714506" MODIFIED="1718586304461" TEXT="Puffer f&#xfc;r Alignment-Anpassung vorhalten">
<icon BUILTIN="flag-yellow"/>
<node CREATED="1718586710311" ID="ID_180065995" MODIFIED="1718586719200" TEXT="Overhead erkennen"/>
<node BACKGROUND_COLOR="#f8f1cb" COLOR="#a50125" CREATED="1718586719814" ID="ID_492092838" MODIFIED="1718586735029" TEXT="Folgeproblem: Gr&#xf6;&#xdf;e der Gesamt-Allokation f&#xfc;r clean-up">
<node COLOR="#338800" CREATED="1718586230120" ID="ID_1182714506" MODIFIED="1718670708508" TEXT="Puffer f&#xfc;r Alignment-Anpassung vorhalten">
<icon BUILTIN="button_ok"/>
<node COLOR="#338800" CREATED="1718586710311" ID="ID_180065995" MODIFIED="1718669740601" TEXT="Overhead erkennen">
<icon BUILTIN="button_ok"/>
<node CREATED="1718669640334" ID="ID_1040101058" MODIFIED="1718669651766" TEXT="schr&#xe4;nke das ein auf over-aligned objects"/>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1718669670802" ID="ID_113943099" MODIFIED="1718669775240" TEXT="Assertion : allozierte Position hat alignof(void*)">
<linktarget COLOR="#b1869d" DESTINATION="ID_113943099" ENDARROW="Default" ENDINCLINATION="354;19;" ID="Arrow_ID_1517471811" SOURCE="ID_1615580773" STARTARROW="None" STARTINCLINATION="430;0;"/>
<icon BUILTIN="yes"/>
</node>
<node CREATED="1718669707782" ID="ID_1171285941" MODIFIED="1718669736566" TEXT="bei gr&#xf6;&#xdf;erem Alignment: Puffer &#x2254; alignment - alignof(void*)">
<icon BUILTIN="idea"/>
</node>
</node>
<node BACKGROUND_COLOR="#efcd8e" COLOR="#a50125" CREATED="1718586719814" ID="ID_492092838" MODIFIED="1718670741937" TEXT="Folgeproblem: Gr&#xf6;&#xdf;e der Gesamt-Allokation f&#xfc;r clean-up">
<icon BUILTIN="messagebox_warning"/>
<node CREATED="1718586736516" ID="ID_1186615431" MODIFIED="1718586891007" TEXT="bisher lie&#xdf; sich diese leicht errechnen">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
auf Basis der buffSiz, d.h. der Gr&#246;&#223;e des reinen Nutzdatenpuffers; auf diese konnte man noch den statisch ermittelbaren Overhead aufschlagen
</p>
</body>
</html>
</richcontent>
</html></richcontent>
</node>
<node CREATED="1718586893951" ID="ID_449167461" MODIFIED="1718587158319" TEXT="aber wir haben das Problem, da&#xdf; nun irgendein Offset oben drauf kommt">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
Der Allocator macht nur eine raw-storage-Allocation, da is nix mit Alignment. Insofern kann der Beginn des gelieferten Speicherbereichs auch &#8222;daneben liegen&#8220; &#8212; so da&#223; wir einen Korrektur-Offset brauchen. Und der l&#228;&#223;t sich nicht systematisch erschlie&#223;en
</p>
</body>
</html>
</richcontent>
</html></richcontent>
</node>
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1718588145261" ID="ID_922709678" MODIFIED="1718634806800" TEXT="also &#xbb;back to square one&#xab; &#x2014; wir m&#xfc;ssen den Offset speichern...">
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1718588145261" ID="ID_922709678" MODIFIED="1718670750721" TEXT="also &#xbb;back to square one&#xab; &#x2014; wir m&#xfc;ssen den Offset speichern...">
<icon BUILTIN="help"/>
<node CREATED="1718634808255" ID="ID_1712579568" MODIFIED="1718634813576" TEXT="nein m&#xfc;ssen wir nicht">
<icon BUILTIN="ksmiletris"/>
</node>
<node CREATED="1718634816323" ID="ID_1531636233" MODIFIED="1718634923456" TEXT="dem Allokator kann der volle Typ gegeben werden">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
Der Aufruf des Allokators erfolgt aus dem Builder, und <i>an der Stelle ist ohne Weiteres der volle Typ konstelliert</i>
</p>
</body>
</html>
</richcontent>
<node COLOR="#5b280f" CREATED="1718635085916" ID="ID_692581133" MODIFIED="1718669795382" TEXT="man kann den Typ differenzieren">
<arrowlink COLOR="#fafec9" DESTINATION="ID_807024103" ENDARROW="Default" ENDINCLINATION="241;-200;" ID="Arrow_ID_1895952533" STARTARROW="None" STARTINCLINATION="-711;55;"/>
<icon BUILTIN="idea"/>
<icon BUILTIN="button_cancel"/>
</node>
<node CREATED="1718634854895" ID="ID_872082102" MODIFIED="1718634878162" TEXT="nur das Front-End ist auf den vereinfachten Typ festgelegt"/>
<node BACKGROUND_COLOR="#ccb59b" COLOR="#6e2a38" CREATED="1718661560425" ID="ID_1260429359" MODIFIED="1718661577273" TEXT="also doch Square One und gut is">
<font ITALIC="true" NAME="SansSerif" SIZE="14"/>
<icon BUILTIN="yes"/>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1718586250781" ID="ID_984021528" MODIFIED="1718586384880" TEXT="das ArrayBucket korrekt im Puffer platzieren">
<linktarget COLOR="#d4095b" DESTINATION="ID_984021528" ENDARROW="Default" ENDINCLINATION="-356;23;" ID="Arrow_ID_628657346" SOURCE="ID_1877181499" STARTARROW="None" STARTINCLINATION="552;-65;"/>
<icon BUILTIN="flag-yellow"/>
</node>
<node COLOR="#338800" CREATED="1718586250781" ID="ID_984021528" MODIFIED="1718670030527" TEXT="das ArrayBucket korrekt im Puffer platzieren">
<linktarget COLOR="#2122d1" DESTINATION="ID_984021528" ENDARROW="Default" ENDINCLINATION="-814;48;" ID="Arrow_ID_628657346" SOURCE="ID_1877181499" STARTARROW="None" STARTINCLINATION="570;-58;"/>
<icon BUILTIN="button_ok"/>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1718587577355" ID="ID_305228810" MODIFIED="1718587885224" TEXT="mit dem Allocator-Framework passiert das nicht korrekt">
<icon BUILTIN="broken-line"/>
<node CREATED="1718587596641" ID="ID_810422938" MODIFIED="1718587728564" TEXT="es g&#xe4;be eine spezielle Variante von operator new, die ein Alignment nimmt">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
...to allocate storage required for a single object whose alignment requirement exceeds __STDCPP_DEFAULT_NEW_ALIGNMENT__
</p>
</body>
</html>
</richcontent>
</html></richcontent>
</node>
<node CREATED="1718587730599" ID="ID_1733586133" MODIFIED="1718587745801" TEXT="die gilt aber nur f&#xfc;r Heap-Allocationen, nicht f&#xfc;r placement-New"/>
<node CREATED="1718587887730" ID="ID_1109606143" MODIFIED="1718587909154" TEXT="normalerweise w&#xfc;rde man (deshalb!) schon die Raw-Allocation getypt machen">
@ -81972,27 +81968,106 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</node>
<node CREATED="1718587914837" ID="ID_1255089684" MODIFIED="1718587997588" TEXT="also &#x201e;bei&#xdf;t&#x201c; uns jetzt wieder genau das Problem mit der dynamischen Puffergr&#xf6;&#xdf;e">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
...weshalb ich ja keinen wirklich passenden statischen Typ f&#252;r ArrayBucket angeben kann, weil die Puffergr&#246;&#223;e erst zur Laufzeit bekannt wird.
</p>
</body>
</html>
</richcontent>
</html></richcontent>
</node>
</node>
<node CREATED="1718588000183" ID="ID_1990467161" MODIFIED="1718588028739" TEXT="&#x27f9; selber machen (aus Gr&#xfc;nden der Klarheit)">
<node CREATED="1718588032517" ID="ID_1492285935" MODIFIED="1718588046931" TEXT="das ist so ein t&#xfc;ckisches Problem, das formuliert man besser explizit"/>
<node CREATED="1718661724546" ID="ID_1163360710" MODIFIED="1718661742337" TEXT="das ist eine so spezielle Lage, da&#xdf; man es per Standard nicht hinbekommt"/>
</node>
<node COLOR="#338800" CREATED="1718661816846" ID="ID_728519799" MODIFIED="1718669938213" TEXT="Implementierung">
<icon BUILTIN="button_ok"/>
<node CREATED="1718661822159" ID="ID_707773010" MODIFIED="1718661916816" TEXT="Alignment auf void* wird vorausgesetzt">
<richcontent TYPE="NOTE"><html>
<head/>
<body>
<p>
das ist eine gewisse Vereinfachung, die aber aller Wahrscheinlichkeit von allen Plattformen erf&#252;llt wird, allein schon weil man sonst an jedem Objekt mit VTable herumfummeln m&#252;&#223;te
</p>
</body>
</html></richcontent>
<node CREATED="1718661841037" ID="ID_1615580773" MODIFIED="1718669775240" TEXT="und per Assertion gepr&#xfc;ft">
<arrowlink COLOR="#b1869d" DESTINATION="ID_113943099" ENDARROW="Default" ENDINCLINATION="354;19;" ID="Arrow_ID_1517471811" STARTARROW="None" STARTINCLINATION="430;0;"/>
</node>
<node CREATED="1718661847298" ID="ID_881168714" MODIFIED="1718661870991" TEXT="(die libStdc++ aligned sogar jede Heap-Allokation auf 16 byte)"/>
</node>
<node CREATED="1718661920360" ID="ID_811952131" MODIFIED="1718661952184" TEXT="&#xdc;ber-Allignment erkennen und einen Puffer-Aufschlag disponieren"/>
<node CREATED="1718661954123" ID="ID_1637790554" MODIFIED="1718661974477" TEXT="die Alignment-Position des Storage-Beginns feststellen"/>
<node CREATED="1718661976016" ID="ID_1431124296" MODIFIED="1718661988004" TEXT="an dieser Stelle ggfs. einen Offset korrigieren"/>
<node CREATED="1718662002813" ID="ID_728179977" MODIFIED="1718662014540" TEXT="den resultierenden Offset im ArrayBucket speichern"/>
<node CREATED="1718662084626" ID="ID_139156973" MODIFIED="1718662101924" TEXT="entsprechende Rest-Menge dese Puffers im ArrayBucket speichern"/>
<node CREATED="1718662108887" ID="ID_1566272413" MODIFIED="1718662153525" TEXT="Deallokation: Puffergr&#xf6;&#xdf;e + gespeicherer Offset &#x27f6; freizugeben"/>
</node>
</node>
<node COLOR="#338800" CREATED="1718067214231" ID="ID_1276439764" LINK="#ID_1830672111" MODIFIED="1718293971538" TEXT="testen"/>
<node COLOR="#338800" CREATED="1718067214231" ID="ID_1276439764" LINK="#ID_1830672111" MODIFIED="1718293971538" TEXT="testen">
<node CREATED="1718669957339" ID="ID_1730347892" MODIFIED="1718669964348" TEXT="Assertion spricht nicht mehr an"/>
<node CREATED="1718669965274" ID="ID_897113879" MODIFIED="1718669987963" TEXT="(au weia ... ob dieser Code wirklich korrekt ist....)">
<icon BUILTIN="smiley-neutral"/>
</node>
</node>
</node>
</node>
</node>
<node CREATED="1718635034149" ID="ID_1461604114" MODIFIED="1718635037864" TEXT="Daten-Layout">
<node CREATED="1718635040841" ID="ID_175622224" MODIFIED="1718635051335" TEXT="Front-End &#x2259; reiner smart-Ptr"/>
<node CREATED="1718635052043" ID="ID_484909431" MODIFIED="1718635056781" TEXT="Storage: ArrayBucket">
<node COLOR="#5b280f" CREATED="1718635061353" ID="ID_807024103" MODIFIED="1718669795382" TEXT="verschiedene Typ-Sichten">
<linktarget COLOR="#fafec9" DESTINATION="ID_807024103" ENDARROW="Default" ENDINCLINATION="241;-200;" ID="Arrow_ID_1895952533" SOURCE="ID_692581133" STARTARROW="None" STARTINCLINATION="-711;55;"/>
<icon BUILTIN="closed"/>
<node CREATED="1718634816323" ID="ID_1531636233" MODIFIED="1718634923456" TEXT="dem Allokator kann der volle Typ gegeben werden">
<richcontent TYPE="NOTE"><html>
<head/>
<body>
<p>
Der Aufruf des Allokators erfolgt aus dem Builder, und <i>an der Stelle ist ohne Weiteres der volle Typ konstelliert</i>
</p>
</body>
</html></richcontent>
</node>
<node CREATED="1718634854895" ID="ID_872082102" MODIFIED="1718635032411" TEXT="nur das Front-End ist auf den vereinfachten Typ festgelegt">
<richcontent TYPE="NOTE"><html>
<head/>
<body>
<p>
F&#252;r den reinen Zugriff gen&#252;gt ein vereinfachter Typ &#8212; insofern dadurch der Zugang zur dynamischen Layout-Information m&#246;glich wird
</p>
</body>
</html></richcontent>
</node>
<node COLOR="#5b280f" CREATED="1718661525539" ID="ID_262957497" MODIFIED="1718661545903" TEXT="das geht so nicht und ist auch gef&#xe4;hrlich">
<icon BUILTIN="stop-sign"/>
<node CREATED="1718661587030" ID="ID_631908211" MODIFIED="1718661620508" TEXT="nein: da das alignas(E) dann jeweils anders w&#xe4;re..."/>
<node CREATED="1718661621590" ID="ID_1425310398" MODIFIED="1718661657638" TEXT="weil der Standard zu std::allocator und zu Alignment wenig sagt"/>
<node CREATED="1718661676330" ID="ID_160664598" MODIFIED="1718661691735" TEXT="weil die libStdC++ bis 2016 das Thema falsch behandelt hat"/>
<node CREATED="1718661693343" ID="ID_1199410471" MODIFIED="1718661710664" TEXT="weil damit kein Verla&#xdf; ist, da&#xdf; andere Implementierungen das richtig machen"/>
</node>
</node>
<node CREATED="1718668599852" ID="ID_409908096" MODIFIED="1718668614795" TEXT="das Objekt selber ist ein Metadaten-Descriptor"/>
<node CREATED="1718668629197" ID="ID_52572573" MODIFIED="1718668685963" TEXT="der eigentliche Daten-Puffer beginnt unmittelbar dahinter">
<richcontent TYPE="NOTE"><html>
<head/>
<body>
<ul>
<li>
verwende sizeof(ArrayBucket&lt;I&gt;) als Offset
</li>
<li>
dimensioniere die eigentliche Allokation so, da&#223; vorne das ArrayBucket reinpasst, und dahinter alle gew&#252;nschten Daten
</li>
</ul>
</body>
</html></richcontent>
</node>
<node CREATED="1718669426413" ID="ID_877825852" MODIFIED="1718669450443" TEXT="der Offset zum Datenpuffer wird gemerkt (und ggfs. vergr&#xf6;&#xdf;ert f&#xfc;r Alignment-Padding)"/>
</node>
</node>
</node>
<node COLOR="#338800" CREATED="1716901426183" FOLDED="true" ID="ID_1212967398" MODIFIED="1718073753857" TEXT="Element-Zugriff und Iteration">
<icon BUILTIN="button_ok"/>
<node COLOR="#5b280f" CREATED="1716901483423" ID="ID_609493193" MODIFIED="1716901839026" TEXT="Element-Spread wird ein Template-Parameter">
@ -84299,7 +84374,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<node COLOR="#338800" CREATED="1718290606176" ID="ID_1457988951" MODIFIED="1718290634409" TEXT="grunds&#xe4;tzlich: Platzierung mit gleichm&#xe4;&#xdf;igem Spread">
<icon BUILTIN="button_ok"/>
</node>
<node COLOR="#338800" CREATED="1718067224015" ID="ID_1830672111" MODIFIED="1718293512166" TEXT="Alignment-Behandlung verifizieren">
<node COLOR="#338800" CREATED="1718067224015" FOLDED="true" ID="ID_1830672111" MODIFIED="1718670970300" TEXT="Alignment-Behandlung verifizieren">
<icon BUILTIN="button_ok"/>
<node COLOR="#e036b2" CREATED="1718294214083" ID="ID_1828779752" MODIFIED="1718294228266" TEXT="tja... wer testet">
<icon BUILTIN="smiley-oh"/>
@ -84314,23 +84389,32 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</body>
</html></richcontent>
</node>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1718586280657" ID="ID_1877181499" MODIFIED="1718586384880" TEXT="leider gen&#xfc;gt das noch nicht...">
<arrowlink COLOR="#d4095b" DESTINATION="ID_984021528" ENDARROW="Default" ENDINCLINATION="-356;23;" ID="Arrow_ID_628657346" STARTARROW="None" STARTINCLINATION="552;-65;"/>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1718586280657" ID="ID_1877181499" MODIFIED="1718670778326" TEXT="leider gen&#xfc;gt das noch nicht...">
<arrowlink COLOR="#2122d1" DESTINATION="ID_984021528" ENDARROW="Default" ENDINCLINATION="-814;48;" ID="Arrow_ID_628657346" STARTARROW="None" STARTINCLINATION="570;-58;"/>
<icon BUILTIN="messagebox_warning"/>
<node BACKGROUND_COLOR="#fafe99" COLOR="#fa002a" CREATED="1718586388686" ID="ID_1438922097" MODIFIED="1718586483948" TEXT="mu&#xdf; explizit das ArrayBucket platzieren">
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1718586388686" ID="ID_1438922097" MODIFIED="1718670914931" TEXT="mu&#xdf; explizit das ArrayBucket platzieren">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
Vorsicht Falle: der Allocator <i>kann das gar nicht machen, </i>wenn man ihm im Sinn von &#187;placement new&#171; explizit die Position vorgibt
</p>
</body>
</html>
</richcontent>
</html></richcontent>
<icon BUILTIN="broken-line"/>
</node>
<node BACKGROUND_COLOR="#c8c0b6" COLOR="#338800" CREATED="1718670780624" ID="ID_1317486460" MODIFIED="1718670924122" TEXT="nach einigem Hin- und Her : Storage-Schema angepa&#xdf;t">
<icon BUILTIN="yes"/>
<node CREATED="1718670806171" ID="ID_758780589" MODIFIED="1718670820051" TEXT="Storage-Bereich beginnt nun hinter dem ArrayBucket"/>
<node CREATED="1718670821016" ID="ID_548260406" MODIFIED="1718670868117" TEXT="die ElementFactory :: create-Methode bekommt nun ein Alignment"/>
<node CREATED="1718670868934" ID="ID_1973205896" MODIFIED="1718670887782" TEXT="sie pr&#xfc;ft nun explizit, ob das Alignmen am Beginn der Storage pa&#xdf;t"/>
<node CREATED="1718670888691" ID="ID_278117840" MODIFIED="1718670901363" TEXT="wir merken uns auch diesen Offset">
<icon BUILTIN="smily_bad"/>
</node>
</node>
<node COLOR="#338800" CREATED="1718670930221" ID="ID_1574991713" MODIFIED="1718670939558" TEXT="Test l&#xe4;uft nun fehlerfrei">
<icon BUILTIN="button_ok"/>
</node>
</node>
</node>
<node COLOR="#338800" CREATED="1718202490965" ID="ID_247674037" MODIFIED="1718297858099" TEXT="Handhabung von non-copyable-Objekten">