Chain-Load: verify building blocks of lazy-init
This commit is contained in:
parent
b00f4501a3
commit
c658512d7b
3 changed files with 190 additions and 57 deletions
|
|
@ -117,7 +117,7 @@ namespace lib {
|
|||
char* anchorAddr = reinterpret_cast<char*> (unConst(anchor));
|
||||
char* adjusted = anchorAddr + offset;
|
||||
void* rawTarget = reinterpret_cast<void*> (adjusted);
|
||||
return static_cast<TAR*> (adjusted);
|
||||
return static_cast<TAR*> (rawTarget);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -129,7 +129,7 @@ namespace lib {
|
|||
* exploited as a trick to allow for automatic late initialisation
|
||||
* in a situation, were a functor needs to capture references.
|
||||
*/
|
||||
const ptrdiff_t PAYLOAD_OFFSET =
|
||||
const ptrdiff_t FUNCTOR_PAYLOAD_OFFSET =
|
||||
[]{
|
||||
size_t slot{42};
|
||||
std::function<RawAddr(void)> probe = [slot]{ return RawAddr(&slot); };
|
||||
|
|
@ -272,6 +272,14 @@ namespace lib {
|
|||
}
|
||||
|
||||
|
||||
template<class SIG>
|
||||
void
|
||||
installEmptyInitialiser()
|
||||
{
|
||||
pendingInit_.reset (new HeapStorage{emptyInitialiser<SIG>()});
|
||||
}
|
||||
|
||||
private:
|
||||
template<class SIG>
|
||||
DelegateType<SIG>
|
||||
emptyInitialiser()
|
||||
|
|
@ -283,40 +291,6 @@ namespace lib {
|
|||
return disabledFunctor;
|
||||
});
|
||||
}
|
||||
template<class SIG>
|
||||
void
|
||||
installEmptyInitialiser()
|
||||
{
|
||||
pendingInit_.reset (new HeapStorage{emptyInitialiser<SIG>()});
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
template<class SIG, class INI>
|
||||
DelegateType<SIG>
|
||||
buildInitialiserDelegate (std::function<SIG>& targetFunctor, INI&& initialiser)
|
||||
{
|
||||
using TargetFun = std::function<SIG>;
|
||||
return DelegateType<SIG>{
|
||||
[performInit = forward<INI> (initialiser)
|
||||
,targetOffset = captureRawAddrOffset (this, &targetFunctor)]
|
||||
(RawAddr location) -> TargetFun&
|
||||
{// apply known offset backwards to find current location of the host object
|
||||
TargetFun* target = relocate<TargetFun> (location, -PAYLOAD_OFFSET);
|
||||
LazyInit* self = relocate<LazyInit> (target, -targetOffset);
|
||||
REQUIRE (self);
|
||||
performInit (self);
|
||||
self->pendingInit_.reset();
|
||||
return *target;
|
||||
}};
|
||||
}
|
||||
|
||||
template<class SIG>
|
||||
DelegateType<SIG>*
|
||||
getPointerToDelegate(HeapStorage& buffer)
|
||||
{
|
||||
return reinterpret_cast<DelegateType<SIG>*> (&buffer);
|
||||
}
|
||||
|
||||
template<class SIG, class INI>
|
||||
PendingInit
|
||||
|
|
@ -329,6 +303,32 @@ namespace lib {
|
|||
targetFunctor = TrojanFun<SIG>::generateTrap (getPointerToDelegate<SIG> (*storageHandle));
|
||||
return storageHandle;
|
||||
}
|
||||
|
||||
template<class SIG>
|
||||
DelegateType<SIG>*
|
||||
getPointerToDelegate(HeapStorage& buffer)
|
||||
{
|
||||
return reinterpret_cast<DelegateType<SIG>*> (&buffer);
|
||||
}
|
||||
|
||||
template<class SIG, class INI>
|
||||
DelegateType<SIG>
|
||||
buildInitialiserDelegate (std::function<SIG>& targetFunctor, INI&& initialiser)
|
||||
{
|
||||
using TargetFun = std::function<SIG>;
|
||||
return DelegateType<SIG>{
|
||||
[performInit = forward<INI> (initialiser)
|
||||
,targetOffset = captureRawAddrOffset (this, &targetFunctor)]
|
||||
(RawAddr location) -> TargetFun&
|
||||
{// apply known offset backwards to find current location of the host object
|
||||
TargetFun* target = relocate<TargetFun> (location, -FUNCTOR_PAYLOAD_OFFSET);
|
||||
LazyInit* self = relocate<LazyInit> (target, -targetOffset);
|
||||
REQUIRE (self);
|
||||
performInit (self);
|
||||
self->pendingInit_.reset();
|
||||
return *target;
|
||||
}};
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -73,22 +73,11 @@ namespace test{
|
|||
void
|
||||
run (Arg)
|
||||
{
|
||||
simpleUse();
|
||||
|
||||
verify_trojanLambda();
|
||||
verify_inlineStorage();
|
||||
// verify_numerics();
|
||||
// verify_adaptMapping();
|
||||
// verify_dynamicChange();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** @test demonstrate a basic usage scenario
|
||||
*/
|
||||
void
|
||||
simpleUse()
|
||||
{
|
||||
verify_TargetRelocation();
|
||||
verify_triggerMechanism();
|
||||
verify_lazyInitialisation();
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -203,6 +192,112 @@ namespace test{
|
|||
|
||||
|
||||
|
||||
/** @test verify navigating an object structure
|
||||
* by applying known offsets consecutively
|
||||
* from a starting point within an remote instance
|
||||
* @remark in the real usage scenario, we know _only_ the offset
|
||||
* and and attempt to find home without knowing the layout.
|
||||
*/
|
||||
void
|
||||
verify_TargetRelocation()
|
||||
{
|
||||
struct Nested
|
||||
{
|
||||
int unrelated{rand()};
|
||||
int anchor{rand()};
|
||||
};
|
||||
struct Demo
|
||||
{
|
||||
Nested nested;
|
||||
virtual ~Demo(){ };
|
||||
virtual RawAddr peek()
|
||||
{
|
||||
return &nested.anchor;
|
||||
}
|
||||
};
|
||||
|
||||
// find out generic offset...
|
||||
const ptrdiff_t offNested = []{
|
||||
Nested probe;
|
||||
return captureRawAddrOffset(&probe, &probe.anchor);
|
||||
}();
|
||||
Demo here;
|
||||
// find out actual offset in existing object
|
||||
const ptrdiff_t offBase = captureRawAddrOffset(&here, &here.nested);
|
||||
|
||||
CHECK (offBase > 0);
|
||||
CHECK (offNested > 0);
|
||||
|
||||
// create a copy far far away...
|
||||
auto farAway = std::make_unique<Demo> (here);
|
||||
|
||||
// reconstruct base address from starting point
|
||||
RawAddr startPoint = farAway->peek();
|
||||
Nested* farNested = relocate<Nested>(startPoint, -offNested);
|
||||
CHECK (here.nested.unrelated == farNested->unrelated);
|
||||
|
||||
Demo* farSelf = relocate<Demo> (farNested, -offBase);
|
||||
CHECK (here.nested.anchor == farSelf->nested.anchor);
|
||||
CHECK (isSameObject (*farSelf, *farAway));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** @test demonstrate the trigger mechanism in isolation
|
||||
*/
|
||||
void
|
||||
verify_triggerMechanism()
|
||||
{
|
||||
using Fun = std::function<float(int)>;
|
||||
Fun theFun;
|
||||
CHECK (not theFun);
|
||||
|
||||
int report{0};
|
||||
auto delegate = [&report](RawAddr insideFun) -> Fun&
|
||||
{
|
||||
auto realFun = [&report](int num)
|
||||
{
|
||||
report += num;
|
||||
return num + 23.55f;
|
||||
};
|
||||
Fun& target = *relocate<Fun>(insideFun, -FUNCTOR_PAYLOAD_OFFSET);
|
||||
report = -42; // as proof that the init-delegate was invoked
|
||||
target = realFun;
|
||||
return target;
|
||||
};
|
||||
CHECK (not theFun);
|
||||
// install the init-»trap«
|
||||
theFun = TrojanFun<float(int)>::generateTrap (&delegate);
|
||||
CHECK (theFun);
|
||||
CHECK (0 == report);
|
||||
|
||||
// invoke function
|
||||
int feed{1+rand()%100};
|
||||
float res = theFun (feed);
|
||||
|
||||
// delegate *and* realFun were invoked
|
||||
CHECK (feed == report + 42);
|
||||
CHECK (res = feed -42 +23.55f);
|
||||
|
||||
// again...
|
||||
report = 0;
|
||||
feed = -1-rand()%20;
|
||||
res = theFun (feed);
|
||||
|
||||
// this time the delegate was *not* invoked,
|
||||
// only the installed realFun
|
||||
CHECK (feed == report);
|
||||
CHECK (res = feed + 23.55f);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** @test demonstrate a basic usage scenario
|
||||
*/
|
||||
void
|
||||
verify_lazyInitialisation()
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -97283,8 +97283,8 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
<icon BUILTIN="pencil"/>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1700786308827" ID="ID_627670298" MODIFIED="1700792001666" TEXT="der Trojanische-Funktor">
|
||||
<icon BUILTIN="pencil"/>
|
||||
<node COLOR="#338800" CREATED="1700786308827" ID="ID_627670298" MODIFIED="1700865645701" TEXT="der Trojanische-Funktor">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
<node COLOR="#5b280f" CREATED="1700786329960" ID="ID_579721558" MODIFIED="1700829943723" TEXT="bettet einen shared_ptr ein">
|
||||
<linktarget COLOR="#e64156" DESTINATION="ID_579721558" ENDARROW="Default" ENDINCLINATION="581;-41;" ID="Arrow_ID_1803799256" SOURCE="ID_1318522029" STARTARROW="None" STARTINCLINATION="-98;-231;"/>
|
||||
<icon BUILTIN="button_cancel"/>
|
||||
|
|
@ -97304,11 +97304,11 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1700786402490" ID="ID_846455233" MODIFIED="1700786418812" TEXT="Trick-Mechanismus zur this-Ermittlung">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1700786427859" ID="ID_569731992" MODIFIED="1700795340778" TEXT="muß zu Beginn »proben«">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node COLOR="#338800" CREATED="1700786427859" ID="ID_569731992" MODIFIED="1700865640264" TEXT="muß zu Beginn »proben«">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1700786446976" ID="ID_646471757" MODIFIED="1700795338010" TEXT="Zusatz-Problem: das λ sieht nur seine capture">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node COLOR="#338800" CREATED="1700786446976" ID="ID_646471757" MODIFIED="1700865636679" TEXT="Zusatz-Problem: das λ sieht nur seine capture">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
<node CREATED="1700786476589" ID="ID_1376774629" MODIFIED="1700786490117" TEXT="⟶ also mehrstufig vorgehen"/>
|
||||
<node CREATED="1700786494226" ID="ID_990128277" MODIFIED="1700786508492" TEXT="generisch das Verhältnis zur std::function ermitteln"/>
|
||||
<node CREATED="1700786514967" ID="ID_1504854205" MODIFIED="1700786531452" TEXT="ebenso das Verhältnis von der std::function zu *this"/>
|
||||
|
|
@ -97393,7 +97393,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
</node>
|
||||
<node CREATED="1700846290266" ID="ID_1685278359" MODIFIED="1700846318281" TEXT="Also bleibt nur: LazyInit packt den eigentlichen Initialiser in einen opaque container"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#f8f1cb" COLOR="#a50125" CREATED="1700856150252" ID="ID_1283688015" MODIFIED="1700856166026" TEXT="Address-Relocation">
|
||||
<node COLOR="#435e98" CREATED="1700856150252" ID="ID_1283688015" MODIFIED="1700865608154" TEXT="Address-Relocation">
|
||||
<icon BUILTIN="messagebox_warning"/>
|
||||
<node BACKGROUND_COLOR="#fafe99" COLOR="#fa002a" CREATED="1700856167326" ID="ID_903304450" MODIFIED="1700856175977" TEXT="der Compiler weint und winselt">
|
||||
<icon BUILTIN="broken-line"/>
|
||||
|
|
@ -97412,6 +97412,44 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1700856538050" ID="ID_30859769" MODIFIED="1700856555062" TEXT="aber die Layout-Annahme selber kann ich leider nicht prüfen">
|
||||
<icon BUILTIN="clanbomber"/>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1700865572986" ID="ID_819138430" MODIFIED="1700865582889" TEXT="zumindest im Test nachgestellt und funktioniert">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1700865668069" ID="ID_96300659" MODIFIED="1700865853252" TEXT="Speicherverwaltung">
|
||||
<icon BUILTIN="pencil"/>
|
||||
<node COLOR="#435e98" CREATED="1700865679180" ID="ID_3672857" MODIFIED="1700865823343">
|
||||
<richcontent TYPE="NODE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
OpaqueHolder<i> mißbraucht</i>
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
<icon BUILTIN="idea"/>
|
||||
<node CREATED="1700865718074" ID="ID_46417679" MODIFIED="1700865732256" TEXT="er setzt eigentlich gemeinsame Basisklasse vorraus"/>
|
||||
<node CREATED="1700865733257" ID="ID_19147628" MODIFIED="1700865768147" TEXT="InPlaceAnyHolder würde den Fall unterstützen, ist aber zu schwergewichtig (VTable)"/>
|
||||
<node CREATED="1700865775966" ID="ID_1852703821" MODIFIED="1700865806222" TEXT="ist hier grade noch so machbar, da wir das Objekt nach Erstellung nur noch verwalten"/>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1700865829132" ID="ID_1420005046" MODIFIED="1700865850429" TEXT="shared_ptr nach Triggern der Initialisierung reset()">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1700865861639" ID="ID_409549839" MODIFIED="1700865919942" TEXT="gegebenes Init-λ adaptieren">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
<node COLOR="#338800" CREATED="1700865886375" ID="ID_594517704" MODIFIED="1700865897328" TEXT="self-Offset capture">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1700865898011" ID="ID_831512370" MODIFIED="1700865904118" TEXT="self-Offset restore">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1700865906981" ID="ID_1800834277" MODIFIED="1700865917596" TEXT="am Ende Referenz auf target-Functor liefern">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node COLOR="#c1019e" CREATED="1700856585458" ID="ID_373199802" MODIFIED="1700856611800" TEXT="ich fühl mich scheiße">
|
||||
|
|
|
|||
Loading…
Reference in a new issue