Chain-Load: verify re-initialisation and copy
...this is a more realistic demo example, which mimics some of the patterns present in RandomDraw. The test also uses lambdas linking to the actual storage location, so that the invocation would crash on a copy; LazyInit was invented to safeguard against this, while still allowing leeway during the initialisation phase in a DSL.
This commit is contained in:
parent
e95f729ad0
commit
04ca79fd65
3 changed files with 332 additions and 36 deletions
|
|
@ -54,7 +54,7 @@
|
|||
** that the »trojan functor« itself is stored somehow embedded into the target object
|
||||
** to be initialised. If there is a fixed distance relation in memory, then the target
|
||||
** can be derived from the self-position of the functor; if this assumption is broken
|
||||
** however, memory corruption and SEGFAULT may be caused.
|
||||
** however, memory corruption and SEGFAULT may be caused.
|
||||
**
|
||||
** @todo 11/2023 at the moment I am just desperately trying to get a bye-product of my
|
||||
** main effort into usable shape and salvage an design idea that sounded clever
|
||||
|
|
@ -73,15 +73,12 @@
|
|||
#define LIB_LAZY_INIT_H
|
||||
|
||||
|
||||
//#include "lib/error.h"
|
||||
//#include "lib/nocopy.hpp"
|
||||
#include "lib/error.h"
|
||||
#include "lib/meta/function.hpp"
|
||||
#include "lib/opaque-holder.hpp"
|
||||
//#include "lib/meta/function-closure.hpp"
|
||||
//#include "lib/util-quant.hpp"
|
||||
#include "lib/util.hpp"
|
||||
|
||||
//#include <functional>
|
||||
#include <functional>
|
||||
#include <utility>
|
||||
#include <memory>
|
||||
|
||||
|
|
@ -90,21 +87,23 @@ namespace lib {
|
|||
namespace err = lumiera::error;
|
||||
|
||||
using lib::meta::_Fun;
|
||||
using lib::meta::_FunArg;
|
||||
using lib::meta::has_Sig;
|
||||
// using std::function;
|
||||
using util::unConst;
|
||||
using std::function;
|
||||
using std::forward;
|
||||
using std::move;
|
||||
|
||||
using RawAddr = void const*;
|
||||
|
||||
|
||||
namespace {// the anonymous namespace of horrors...
|
||||
|
||||
inline ptrdiff_t
|
||||
captureRawAddrOffset (RawAddr anchor, RawAddr subject)
|
||||
{
|
||||
// Dear Mr.Compiler, please get out of my way.
|
||||
// I just sincerely want to shoot myself into my foot...
|
||||
// I just genuinely want to shoot myself into my foot...
|
||||
char* anchorAddr = reinterpret_cast<char*> (unConst(anchor));
|
||||
char* subjectAddr = reinterpret_cast<char*> (unConst(subject));
|
||||
return subjectAddr - anchorAddr;
|
||||
|
|
@ -140,7 +139,10 @@ namespace lib {
|
|||
"apply small-object optimisation with inline storage."};
|
||||
return captureRawAddrOffset (functor,payload);
|
||||
}();
|
||||
}
|
||||
//
|
||||
}//(End)low-level manipulations
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
|
|
@ -171,12 +173,11 @@ namespace lib {
|
|||
* and then to forward the invocation to the actual
|
||||
* function, which should have been initialised
|
||||
* by the delegate invoked.
|
||||
* @param delegate a functor object pass invocation;
|
||||
* @param delegate a functor object to forward invocation;
|
||||
* the delegate must return a reference to the
|
||||
* actual function implementation to invoke.
|
||||
* Must be heap-allocated.
|
||||
* @return a lightweight lambda usable as trigger.
|
||||
* @note takes ownership of the delegate
|
||||
*/
|
||||
template<class DEL>
|
||||
static auto
|
||||
|
|
@ -195,10 +196,18 @@ namespace lib {
|
|||
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
|
||||
|
||||
struct EmptyBase { };
|
||||
|
||||
/**************************************************************//**
|
||||
* Mix-in for lazy/delayed initialisation of an embedded functor.
|
||||
* This allows to keep the overall object (initially) copyable,
|
||||
* while later preventing copy once the functor was »engaged«.
|
||||
* Initially, only a »trap« is installed into the functor,
|
||||
* invoking an initialisation closure on first use.
|
||||
*/
|
||||
template<class PAR>
|
||||
template<class PAR =EmptyBase>
|
||||
class LazyInit
|
||||
: public PAR
|
||||
{
|
||||
|
|
@ -209,8 +218,10 @@ namespace lib {
|
|||
using HeapStorage = InPlaceBuffer<PlaceholderType>;
|
||||
using PendingInit = std::shared_ptr<HeapStorage>;
|
||||
|
||||
/** manage heap storage for a pending initialisation closure */
|
||||
PendingInit pendingInit_;
|
||||
|
||||
|
||||
PendingInit const&
|
||||
__trapLocked (PendingInit const& init)
|
||||
{
|
||||
|
|
@ -232,13 +243,27 @@ namespace lib {
|
|||
}
|
||||
|
||||
|
||||
|
||||
protected:
|
||||
struct MarkDisabled{};
|
||||
|
||||
/** @internal allows derived classes to leave the initialiser deliberately disabled */
|
||||
template<typename...ARGS>
|
||||
LazyInit (MarkDisabled, ARGS&& ...parentCtorArgs)
|
||||
: PAR(forward<ARGS> (parentCtorArgs)...)
|
||||
, pendingInit_{}
|
||||
{ }
|
||||
|
||||
|
||||
public:
|
||||
/** prepare an initialiser to be activated on first use */
|
||||
template<class SIG, class INI, typename...ARGS>
|
||||
LazyInit (std::function<SIG>& targetFunctor, INI&& initialiser, ARGS&& ...parentCtorArgs)
|
||||
: PAR(forward<ARGS> (parentCtorArgs)...)
|
||||
, pendingInit_{prepareInitialiser (targetFunctor, forward<INI> (initialiser))}
|
||||
{ }
|
||||
|
||||
|
||||
LazyInit (LazyInit const& ref)
|
||||
: PAR{ref}
|
||||
, pendingInit_{__trapLocked (ref.pendingInit_)}
|
||||
|
|
@ -272,6 +297,12 @@ namespace lib {
|
|||
}
|
||||
|
||||
|
||||
bool
|
||||
isInit() const
|
||||
{
|
||||
return not pendingInit_;
|
||||
}
|
||||
|
||||
template<class SIG>
|
||||
void
|
||||
installEmptyInitialiser()
|
||||
|
|
@ -279,7 +310,15 @@ namespace lib {
|
|||
pendingInit_.reset (new HeapStorage{emptyInitialiser<SIG>()});
|
||||
}
|
||||
|
||||
private:
|
||||
template<class SIG, class INI>
|
||||
void
|
||||
installInitialiser (std::function<SIG>& targetFunctor, INI&& initialiser)
|
||||
{
|
||||
pendingInit_ = prepareInitialiser (targetFunctor, forward<INI> (initialiser));
|
||||
}
|
||||
|
||||
|
||||
private: /* ========== setup of the initialisation mechanism ========== */
|
||||
template<class SIG>
|
||||
DelegateType<SIG>
|
||||
emptyInitialiser()
|
||||
|
|
@ -306,7 +345,7 @@ namespace lib {
|
|||
|
||||
template<class SIG>
|
||||
DelegateType<SIG>*
|
||||
getPointerToDelegate(HeapStorage& buffer)
|
||||
getPointerToDelegate (HeapStorage& buffer)
|
||||
{
|
||||
return reinterpret_cast<DelegateType<SIG>*> (&buffer);
|
||||
}
|
||||
|
|
@ -316,6 +355,7 @@ namespace lib {
|
|||
buildInitialiserDelegate (std::function<SIG>& targetFunctor, INI&& initialiser)
|
||||
{
|
||||
using TargetFun = std::function<SIG>;
|
||||
using ExpectedArg = _FunArg<INI>;
|
||||
return DelegateType<SIG>{
|
||||
[performInit = forward<INI> (initialiser)
|
||||
,targetOffset = captureRawAddrOffset (this, &targetFunctor)]
|
||||
|
|
@ -324,9 +364,10 @@ namespace lib {
|
|||
TargetFun* target = relocate<TargetFun> (location, -FUNCTOR_PAYLOAD_OFFSET);
|
||||
LazyInit* self = relocate<LazyInit> (target, -targetOffset);
|
||||
REQUIRE (self);
|
||||
performInit (self);
|
||||
self->pendingInit_.reset();
|
||||
return *target;
|
||||
// invoke init, possibly downcast to derived *self
|
||||
performInit (static_cast<ExpectedArg> (self));
|
||||
self->pendingInit_.reset(); // release storage
|
||||
return *target; // invoked by the »Trojan« to yield first result
|
||||
}};
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@
|
|||
#include "lib/test/diagnostic-output.hpp" /////////////////////TODO TODOH
|
||||
#include "lib/util.hpp"
|
||||
|
||||
//#include <array>
|
||||
#include <memory>
|
||||
|
||||
|
||||
|
||||
|
|
@ -42,10 +42,10 @@ namespace lib {
|
|||
namespace test{
|
||||
|
||||
// using util::_Fmt;
|
||||
using std::make_unique;
|
||||
using util::isSameObject;
|
||||
using lib::meta::isFunMember;
|
||||
// using lib::meta::_FunRet;
|
||||
// using err::LUMIERA_ERROR_LIFECYCLE;
|
||||
using err::LUMIERA_ERROR_LIFECYCLE;
|
||||
|
||||
|
||||
|
||||
|
|
@ -78,6 +78,7 @@ namespace test{
|
|||
verify_TargetRelocation();
|
||||
verify_triggerMechanism();
|
||||
verify_lazyInitialisation();
|
||||
verify_complexUsageWithCopy();
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -87,7 +88,7 @@ namespace test{
|
|||
* # the _target function_ finally to be invoked performs a verifiable computation
|
||||
* # the _delegate_ receives an memory location and returns a reference to the target
|
||||
* # the generated _»trojan λ«_ captures its own address, invokes the delegate,
|
||||
* retrieves a reference to a target functor, and invokes these with actual arguments.
|
||||
* retrieves a reference to a target functor, and finally invokes this with actual arguments.
|
||||
* @remark the purpose of this convoluted scheme is for the _delegate to perform initialisation,_
|
||||
* taking into account the current memory location „sniffed“ by the trojan.
|
||||
*/
|
||||
|
|
@ -119,16 +120,15 @@ namespace test{
|
|||
return fun;
|
||||
};
|
||||
using Delegate = decltype(delegate);
|
||||
Delegate *delP = new Delegate(delegate);
|
||||
auto delP = make_unique<Delegate> (delegate);
|
||||
|
||||
// verify the heap-allocated copy of the delegate behaves as expected
|
||||
location = nullptr;
|
||||
CHECK (beacon+c == (*delP)(this)(c));
|
||||
CHECK (location == this);
|
||||
|
||||
// now (finally) build the »trap function«,
|
||||
// taking ownership of the heap-allocated delegate copy
|
||||
auto trojanLambda = TrojanFun<Sig>::generateTrap (delP);
|
||||
// now (finally) build the »trap function«...
|
||||
auto trojanLambda = TrojanFun<Sig>::generateTrap (delP.get());
|
||||
CHECK (sizeof(trojanLambda) == sizeof(size_t));
|
||||
|
||||
// on invocation...
|
||||
|
|
@ -138,7 +138,7 @@ namespace test{
|
|||
CHECK (beacon+c == trojanLambda(c));
|
||||
CHECK (location == &trojanLambda);
|
||||
|
||||
// repeat that with a copy, and changed beacon value
|
||||
// repeat same with a copy, and changed beacon value
|
||||
auto trojanClone = trojanLambda;
|
||||
beacon = rand();
|
||||
c = beacon % 55;
|
||||
|
|
@ -150,17 +150,17 @@ namespace test{
|
|||
|
||||
|
||||
|
||||
/** @test verify that std::function indeed stores a simple functor inline
|
||||
/** @test verify that std::function indeed stores a simple functor inline.
|
||||
* @remark The implementation of LazyInit relies crucially on a known optimisation
|
||||
* in the standard library ─ which unfortunately is not guaranteed by the standard:
|
||||
* Typically, std::function will apply _small object optimisation_ to place a very
|
||||
* small functor directly into the wrapper, if the payload has a trivial copy-ctor.
|
||||
* Libstdc++ is known to be rather restrictive, other implementations trade increased
|
||||
* storage size of std::function against more optimisation possibilities.
|
||||
* `Libstdc++` is known to be rather restrictive, while other implementations trade
|
||||
* increased storage size of std::function against more optimisation possibilities.
|
||||
* LazyInit exploits this optimisation to „spy“ about the current object location,
|
||||
* to allow executing the lazy initialisation on first use, without further help
|
||||
* allowing to execute the lazy initialisation on first use, without further help
|
||||
* by client code. This trickery seems to be the only way, since λ-capture by reference
|
||||
* is broken after copying or moving the host object (which is required for DSL use).
|
||||
* is broken after copying or moving the host object (typically required for DSL use).
|
||||
* In case this turns out to be fragile, LazyInit should become a "LateInit" and needs
|
||||
* help by the client or the user to trigger initialisation; alternatively the DSL
|
||||
* could be split off into a separate builder object distinct from RandomDraw.
|
||||
|
|
@ -169,7 +169,7 @@ namespace test{
|
|||
verify_inlineStorage()
|
||||
{
|
||||
// char payload[24];// ◁─────────────────────────────── use this to make the test fail....
|
||||
const char* payload = "Outer Space";
|
||||
const char* payload = "please look elsewhere";
|
||||
auto lambda = [payload]{ return RawAddr(&payload); };
|
||||
|
||||
RawAddr location = lambda();
|
||||
|
|
@ -196,7 +196,7 @@ namespace test{
|
|||
* 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.
|
||||
* and attempt to find home without knowing the layout.
|
||||
*/
|
||||
void
|
||||
verify_TargetRelocation()
|
||||
|
|
@ -229,7 +229,7 @@ namespace test{
|
|||
CHECK (offNested > 0);
|
||||
|
||||
// create a copy far far away...
|
||||
auto farAway = std::make_unique<Demo> (here);
|
||||
auto farAway = make_unique<Demo> (here);
|
||||
|
||||
// reconstruct base address from starting point
|
||||
RawAddr startPoint = farAway->peek();
|
||||
|
|
@ -322,6 +322,89 @@ namespace test{
|
|||
CHECK (1 == invoked);
|
||||
CHECK (init);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** elaborate setup used for integration test */
|
||||
struct LazyDemo
|
||||
: LazyInit<>
|
||||
{
|
||||
using Fun = std::function<int(int)>;
|
||||
|
||||
int seed{0};
|
||||
Fun fun; // ◁────────────────────────────────── this will be initialised lazily....
|
||||
|
||||
template<typename FUN>
|
||||
auto
|
||||
buildInit (FUN&& fun2install)
|
||||
{
|
||||
return [theFun = forward<FUN> (fun2install)]
|
||||
(LazyDemo* self)
|
||||
{
|
||||
CHECK (self);
|
||||
self->fun = [self, chain = move(theFun)]
|
||||
(int i)
|
||||
{
|
||||
return chain (i + self->seed); // Note: binding to actual instance location
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
LazyDemo()
|
||||
: LazyInit{MarkDisabled()}
|
||||
, fun{}
|
||||
{
|
||||
installInitialiser(fun, buildInit([](int){ return 0; }));
|
||||
}
|
||||
|
||||
template<typename FUN>
|
||||
LazyDemo(FUN&& someFun)
|
||||
: LazyInit{MarkDisabled()}
|
||||
, fun{}
|
||||
{
|
||||
installInitialiser(fun, buildInit (forward<FUN> (someFun)));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @test use an elaborately constructed example to cover more corner cases
|
||||
* - the function to manage and initialise lazily is _a member_ of the _derived class_
|
||||
* - the initialisation routine _adapts_ this function and links it with the current
|
||||
* object location; thus, invoking this function on a copy would crash / corrupt memory.
|
||||
* - however, as long as initialisation has not been triggered, LazyDemo instances can be
|
||||
* copied; they may even be assigned to existing instances, overwriting their state.
|
||||
*/
|
||||
void
|
||||
verify_complexUsageWithCopy()
|
||||
{
|
||||
LazyDemo d1;
|
||||
CHECK (not d1.isInit()); // not initialised, since function was not invoked yet
|
||||
CHECK (d1.fun); // the functor is not empty anymore, since the »trap« was installed
|
||||
|
||||
d1.seed = 2;
|
||||
CHECK (0 == d1.fun(22)); // d1 was default initialised and thus got the "return 0" function
|
||||
CHECK (d1.isInit()); // first invocation also triggered the init-routine
|
||||
|
||||
// is »engaged« after init and rejects move / copy
|
||||
VERIFY_ERROR (LIFECYCLE, LazyDemo dx{move(d1)} );
|
||||
|
||||
|
||||
d1 = LazyDemo{[](int i) // assign a fresh copy (discarding any state in d1)
|
||||
{
|
||||
return i + 1; // using a "return i+1" function
|
||||
}};
|
||||
CHECK (not d1.isInit());
|
||||
CHECK (d1.seed == 0); // assignment indeed erased any existing settings (seed≔2)
|
||||
CHECK (d1.fun);
|
||||
|
||||
CHECK (23 == d1.fun(22)); // new function was tied in (while also referring to self->seed)
|
||||
CHECK (d1.isInit());
|
||||
d1.seed = 3; // set the seed
|
||||
CHECK (26 == d1.fun(22)); // seed value is picked up dynamically
|
||||
|
||||
VERIFY_ERROR (LIFECYCLE, LazyDemo dx{move(d1)} );
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -97280,6 +97280,93 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
</node>
|
||||
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1700779275391" ID="ID_1990626821" MODIFIED="1700792011791" TEXT="LazyInit_test.cpp">
|
||||
<icon BUILTIN="pencil"/>
|
||||
<node COLOR="#338800" CREATED="1700875396864" ID="ID_1861612135" MODIFIED="1700875416597" TEXT="verify_trojanLambda">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1700875396864" FOLDED="true" ID="ID_1355973273" MODIFIED="1700875456048" TEXT="verify_inlineStorage">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
<node CREATED="1700875427276" ID="ID_403717073" MODIFIED="1700875442853" TEXT="Untersuchungen zum Verhalten von std::function (libStc++8)"/>
|
||||
<node CREATED="1700875443865" ID="ID_1990486288" MODIFIED="1700875455003" TEXT="entwickle ein Prädikat um Heap-Storage zu erkennen"/>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1700875396865" FOLDED="true" ID="ID_1084080047" MODIFIED="1700875514743" TEXT="verify_TargetRelocation">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
<node CREATED="1700875464620" ID="ID_758182999" MODIFIED="1700875483607" TEXT="spiele die grauenhafte Pointer-Arrithmetik mal im Labor durch"/>
|
||||
<node CREATED="1700875484403" ID="ID_52550971" MODIFIED="1700875504989" TEXT="verwende bewußt Beispiel mit normalen Structs, um Offsets jenseits der Slots zu bekommen"/>
|
||||
<node CREATED="1700875505873" ID="ID_1289960190" MODIFIED="1700875513435" TEXT="funktioniert, auch mit einem halb-Offset"/>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1700875396865" FOLDED="true" ID="ID_1339757746" MODIFIED="1700875579772" TEXT="verify_triggerMechanism">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
<node CREATED="1700875518455" ID="ID_1980265417" MODIFIED="1700875542195" TEXT="baue für mein eigenes Verständnis nochmal den Trigger-Mechanismus zu fuß nach"/>
|
||||
<node CREATED="1700875543520" ID="ID_92771542" MODIFIED="1700875550945" TEXT="könnte auch zur Dokumentation hilfreich sein"/>
|
||||
<node CREATED="1700875554730" ID="ID_1759963840" MODIFIED="1700875577811" TEXT="(an den eigentlichen Trigger kommt man nicht ran, da der zu fest mit LazyInit verkopelt ist)"/>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1700875396865" FOLDED="true" ID="ID_407572310" MODIFIED="1700875618722" TEXT="verify_lazyInitialisation">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
<node CREATED="1700875581782" ID="ID_902572155" MODIFIED="1700875588657" TEXT="spiele ein bewußt einfaches Beispiel durch"/>
|
||||
<node CREATED="1700875589219" ID="ID_831881033" MODIFIED="1700875597848" TEXT="LazyInit direkt als top-level-Klasse"/>
|
||||
<node CREATED="1700875598444" ID="ID_373137353" MODIFIED="1700875604078" TEXT="erbt direkt von einer function"/>
|
||||
<node CREATED="1700875605831" ID="ID_422784862" MODIFIED="1700875617830" TEXT="prüfe, daß der Initialiser nur einmal läuft"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1700875396866" ID="ID_1176534247" MODIFIED="1700875620954" TEXT="verify_complexUsageWithCopy">
|
||||
<icon BUILTIN="pencil"/>
|
||||
<node CREATED="1700875626785" ID="ID_1403498874" MODIFIED="1700875642770" TEXT="baue bewußt ein möglichst verschlungenes (realisitisches) Beispiel"/>
|
||||
<node CREATED="1700875643550" ID="ID_1209015029" MODIFIED="1700875657152" TEXT="macht eine nicht-triviale Verknpüfung, d.h. adaptiert die gegebene Funktion noch"/>
|
||||
<node CREATED="1700875658155" ID="ID_278966157" MODIFIED="1700875690711">
|
||||
<richcontent TYPE="NODE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
die Funktion ist dieses Mal <b>ein Feld</b> <i>im </i>abgeleiteten Objekt (yess!)
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</node>
|
||||
<node CREATED="1700875716980" ID="ID_649768460" MODIFIED="1700875737214" TEXT="default-ctor installiert fallback-Funkction"/>
|
||||
<node CREATED="1700875738346" ID="ID_1264877418" MODIFIED="1700875746853" TEXT="ein ctor mit explizit gegebener Function"/>
|
||||
<node CREATED="1700875748355" ID="ID_103299394" MODIFIED="1700875753491" TEXT="Testfälle">
|
||||
<node COLOR="#338800" CREATED="1700875754418" ID="ID_660767780" MODIFIED="1700878189835" TEXT="default-Objekt">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
<node COLOR="#338800" CREATED="1700875764710" ID="ID_695451647" MODIFIED="1700878192178" TEXT="Zustand nach Konstruktion">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
<node COLOR="#435e98" CREATED="1700875806915" ID="ID_1651702944" MODIFIED="1700878163584" TEXT="Function-Feld ist nicht initialisiert">
|
||||
<icon BUILTIN="broken-line"/>
|
||||
<node CREATED="1700875834493" ID="ID_1564551745" MODIFIED="1700875839823" TEXT="not d1.fun"/>
|
||||
<node CREATED="1700875841150" ID="ID_88050393" MODIFIED="1700875849677" TEXT="throws invalid_function_call"/>
|
||||
<node COLOR="#435e98" CREATED="1700875853129" ID="ID_502226878" MODIFIED="1700878147483" TEXT="Analyse(debugger)">
|
||||
<icon BUILTIN="list"/>
|
||||
<node CREATED="1700876345072" ID="ID_1248014496" MODIFIED="1700876355643" TEXT="Ha! Feld wird nach Basisklasse initialisiert"/>
|
||||
<node CREATED="1700876356351" ID="ID_1118675302" MODIFIED="1700876372841" TEXT="d.h. der bereits platzierte Trojaner wird überschrieben"/>
|
||||
<node CREATED="1700876373789" ID="ID_1710398995" MODIFIED="1700876376930" TEXT="oh wie schade"/>
|
||||
</node>
|
||||
<node COLOR="#435e98" CREATED="1700876399272" ID="ID_96046426" MODIFIED="1700878150904" TEXT="⟹ brauche">
|
||||
<node CREATED="1700876408887" ID="ID_1752186900" MODIFIED="1700876416771" TEXT="Leer-Initialisierung von LazyInit"/>
|
||||
<node CREATED="1700876426498" ID="ID_437510896" MODIFIED="1700876503102" TEXT="Setter für späteres Installieren">
|
||||
<arrowlink COLOR="#4d5b96" DESTINATION="ID_932710079" ENDARROW="Default" ENDINCLINATION="776;-58;" ID="Arrow_ID_1938279623" STARTARROW="None" STARTINCLINATION="-349;33;"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1700878155031" ID="ID_980233097" MODIFIED="1700878157482" TEXT="tut">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1700875772636" ID="ID_1469062137" MODIFIED="1700878173636" TEXT="aufrufen : default-Function läuft">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1700875784147" ID="ID_542765389" MODIFIED="1700878175169" TEXT="Zustand danach">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1700875788327" ID="ID_1387936235" MODIFIED="1700878176498" TEXT="weise ein Objekt mit explizit gebundener Funktion zu">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1700878177787" ID="ID_707719092" MODIFIED="1700878185308" TEXT="engaged / reject copy">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1700786308827" ID="ID_627670298" MODIFIED="1700865645701" TEXT="der Trojanische-Funktor">
|
||||
|
|
@ -97451,12 +97538,97 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1700871032790" ID="ID_1056099589" MODIFIED="1700878109349" TEXT="bereits installierten Initialiser ersetzen">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
<node CREATED="1700871049276" ID="ID_932710079" MODIFIED="1700876495342" TEXT="in der Tat ... das kann vorkommen">
|
||||
<linktarget COLOR="#4d5b96" DESTINATION="ID_932710079" ENDARROW="Default" ENDINCLINATION="776;-58;" ID="Arrow_ID_1938279623" SOURCE="ID_437510896" STARTARROW="None" STARTINCLINATION="-349;33;"/>
|
||||
<icon BUILTIN="yes"/>
|
||||
</node>
|
||||
<node CREATED="1700871060514" ID="ID_600057244" MODIFIED="1700871092594" TEXT="sollte der realisierte Mechanismus auch können...">
|
||||
<node CREATED="1700871098989" ID="ID_700052304" MODIFIED="1700871109959" TEXT="und zwar macht hier shared_ptr die ganze Magie"/>
|
||||
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1700871113915" ID="ID_1741357094" MODIFIED="1700871131876" TEXT="die Initialisierungen können sich durchaus verzweigen">
|
||||
<icon BUILTIN="messagebox_warning"/>
|
||||
</node>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1700871143583" ID="ID_1088454070" MODIFIED="1700878102782" TEXT="muß dann aber eine Setter-Funktion public machen">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1700876522892" ID="ID_199433026" MODIFIED="1700878099429" TEXT="brauche dann auch einen Leer-Init-Zustand">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1700878072770" ID="ID_1728628936" MODIFIED="1700878084969" TEXT="Prolbem: ctor-Signatur zweideutig">
|
||||
<icon BUILTIN="messagebox_warning"/>
|
||||
</node>
|
||||
<node CREATED="1700878086446" ID="ID_1368715362" MODIFIED="1700878097543" TEXT="lösen durch ein MarkDisabled() - Tag">
|
||||
<icon BUILTIN="idea"/>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#f8f1cb" COLOR="#a50125" CREATED="1700871279919" ID="ID_1126055663" MODIFIED="1700871683297">
|
||||
<richcontent TYPE="NODE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
hier besteht ein latentes semantsiches Problem:
|
||||
</p>
|
||||
<p>
|
||||
lazyInit ⟹ Objekt ist erst mal <i>noch nicht ganz</i> initialisiert
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
<arrowlink COLOR="#a11470" DESTINATION="ID_615420321" ENDARROW="Default" ENDINCLINATION="-38;-156;" ID="Arrow_ID_1147775137" STARTARROW="None" STARTINCLINATION="-409;35;"/>
|
||||
<icon BUILTIN="messagebox_warning"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node COLOR="#c1019e" CREATED="1700856585458" ID="ID_373199802" MODIFIED="1700856611800" TEXT="ich fühl mich scheiße">
|
||||
<font NAME="SansSerif" SIZE="16"/>
|
||||
<icon BUILTIN="smily_bad"/>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#f8f1cb" COLOR="#a50125" CREATED="1700871359629" ID="ID_615420321" MODIFIED="1700871683297" TEXT="kann nicht alle Usage-Pattern abdecken">
|
||||
<linktarget COLOR="#a11470" DESTINATION="ID_615420321" ENDARROW="Default" ENDINCLINATION="-38;-156;" ID="Arrow_ID_1147775137" SOURCE="ID_1126055663" STARTARROW="None" STARTINCLINATION="-409;35;"/>
|
||||
<icon BUILTIN="broken-line"/>
|
||||
<node CREATED="1700871415082" ID="ID_1938566813" MODIFIED="1700871510648" TEXT="es geht allerdings um ein ehr fortgeschrittenes Szenario">
|
||||
<icon BUILTIN="info"/>
|
||||
<node CREATED="1700871453605" ID="ID_1763209918" MODIFIED="1700871474745" TEXT="Installieren einer dynamischen Manipulation über ein bestehendes Mapping">
|
||||
<icon BUILTIN="forward"/>
|
||||
</node>
|
||||
<node CREATED="1700871479242" ID="ID_269811751" MODIFIED="1700871501010" TEXT="es funktioniert, sofern man die erste Konfiguration tatsächlich einmal aktiviert">
|
||||
<icon BUILTIN="idea"/>
|
||||
</node>
|
||||
<node CREATED="1700871434600" ID="ID_211010484" MODIFIED="1700871446348" TEXT="im Test hab ich das, aber ob es jemals gebraucht wird?"/>
|
||||
</node>
|
||||
<node CREATED="1700871595595" ID="ID_370281479" MODIFIED="1700871614083" TEXT="es ließe sich allerdings durchaus realisieren">
|
||||
<icon BUILTIN="smiley-neutral"/>
|
||||
<node CREATED="1700871621703" ID="ID_350569158" MODIFIED="1700871630435" TEXT="und zwar, indem man Initialisierer verkettet"/>
|
||||
<node CREATED="1700871631338" ID="ID_382997669" MODIFIED="1700878229737" TEXT="iz werds aba wuid">
|
||||
<icon BUILTIN="smiley-angry"/>
|
||||
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1700871688167" ID="ID_393112560" MODIFIED="1700871731833" TEXT="warum sehe ich immer sofort noch eine Lösung??">
|
||||
<icon BUILTIN="smiley-oh"/>
|
||||
<icon BUILTIN="smily_bad"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1700871698421" ID="ID_856751270" MODIFIED="1700871709596" TEXT="warum gebe ich mich nicht längst geschlagen???">
|
||||
<icon BUILTIN="help"/>
|
||||
<node CREATED="1700871745466" ID="ID_143069674" MODIFIED="1700871754102" TEXT="die Lektion ist inwsichen sowas von klar"/>
|
||||
<node CREATED="1700871754718" ID="ID_845938579" MODIFIED="1700871770128">
|
||||
<richcontent TYPE="NODE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
dieses Design ist <b>MIST</b>
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1700577811739" ID="ID_1356052727" MODIFIED="1700623391805" TEXT="Konfigurations-DSL aufbauen">
|
||||
|
|
|
|||
Loading…
Reference in a new issue