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:
parent
dc6c8e0858
commit
09c8c2a29f
4 changed files with 189 additions and 104 deletions
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
|
|
|
|||
|
|
@ -81799,7 +81799,7 @@ Date:   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:   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 ⟶ void*">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
|
|
@ -81895,76 +81895,72 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
<node COLOR="#338800" CREATED="1718067163803" ID="ID_1053644006" MODIFIED="1718067198266" TEXT=""sizeof(TY)" ⟼ reqSiz<TY>()">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1718586230120" ID="ID_1182714506" MODIFIED="1718586304461" TEXT="Puffer fü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öße der Gesamt-Allokation für clean-up">
|
||||
<node COLOR="#338800" CREATED="1718586230120" ID="ID_1182714506" MODIFIED="1718670708508" TEXT="Puffer fü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ä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ößerem Alignment: Puffer ≔ alignment - alignof(void*)">
|
||||
<icon BUILTIN="idea"/>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#efcd8e" COLOR="#a50125" CREATED="1718586719814" ID="ID_492092838" MODIFIED="1718670741937" TEXT="Folgeproblem: Größe der Gesamt-Allokation für clean-up">
|
||||
<icon BUILTIN="messagebox_warning"/>
|
||||
<node CREATED="1718586736516" ID="ID_1186615431" MODIFIED="1718586891007" TEXT="bisher ließ sich diese leicht errechnen">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
auf Basis der buffSiz, d.h. der Größ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ß 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 „daneben liegen“ — so daß wir einen Korrektur-Offset brauchen. Und der läßt sich nicht systematisch erschließen
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1718588145261" ID="ID_922709678" MODIFIED="1718634806800" TEXT="also »back to square one« — wir müssen den Offset speichern...">
|
||||
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1718588145261" ID="ID_922709678" MODIFIED="1718670750721" TEXT="also »back to square one« — wir müssen den Offset speichern...">
|
||||
<icon BUILTIN="help"/>
|
||||
<node CREATED="1718634808255" ID="ID_1712579568" MODIFIED="1718634813576" TEXT="nein mü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ä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ür Heap-Allocationen, nicht für placement-New"/>
|
||||
<node CREATED="1718587887730" ID="ID_1109606143" MODIFIED="1718587909154" TEXT="normalerweise würde man (deshalb!) schon die Raw-Allocation getypt machen">
|
||||
|
|
@ -81972,27 +81968,106 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
</node>
|
||||
<node CREATED="1718587914837" ID="ID_1255089684" MODIFIED="1718587997588" TEXT="also „beißt“ uns jetzt wieder genau das Problem mit der dynamischen Puffergröße">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
...weshalb ich ja keinen wirklich passenden statischen Typ für ArrayBucket angeben kann, weil die Puffergröße erst zur Laufzeit bekannt wird.
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1718588000183" ID="ID_1990467161" MODIFIED="1718588028739" TEXT="⟹ selber machen (aus Gründen der Klarheit)">
|
||||
<node CREATED="1718588032517" ID="ID_1492285935" MODIFIED="1718588046931" TEXT="das ist so ein tückisches Problem, das formuliert man besser explizit"/>
|
||||
<node CREATED="1718661724546" ID="ID_1163360710" MODIFIED="1718661742337" TEXT="das ist eine so spezielle Lage, daß 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üllt wird, allein schon weil man sonst an jedem Objekt mit VTable herumfummeln müßte
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
<node CREATED="1718661841037" ID="ID_1615580773" MODIFIED="1718669775240" TEXT="und per Assertion geprü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="Ü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öße + gespeicherer Offset ⟶ 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 ≙ 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ür den reinen Zugriff genügt ein vereinfachter Typ — insofern dadurch der Zugang zur dynamischen Layout-Information mö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ährlich">
|
||||
<icon BUILTIN="stop-sign"/>
|
||||
<node CREATED="1718661587030" ID="ID_631908211" MODIFIED="1718661620508" TEXT="nein: da das alignas(E) dann jeweils anders wä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ß ist, daß 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<I>) als Offset
|
||||
</li>
|
||||
<li>
|
||||
dimensioniere die eigentliche Allokation so, daß vorne das ArrayBucket reinpasst, und dahinter alle gewü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ößert fü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:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
<node COLOR="#338800" CREATED="1718290606176" ID="ID_1457988951" MODIFIED="1718290634409" TEXT="grundsätzlich: Platzierung mit gleichmäß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:   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ü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ü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ß explizit das ArrayBucket platzieren">
|
||||
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1718586388686" ID="ID_1438922097" MODIFIED="1718670914931" TEXT="muß 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 »placement new« 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ß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üft nun explizit, ob das Alignmen am Beginn der Storage paß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ä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">
|
||||
|
|
|
|||
Loading…
Reference in a new issue