Library: now able to provide a self-managed thread

After quite some detours, with this take I'm finally able to
provide a stringent design to embody all the variants of thread start
encountered in practice in the Lumiera code base.

Especially the *self-managed* thread is now represented as a special-case
of a lifecycle-hook, and can be embodied into a builder front-end,
able to work with any client-provided thread-wrapper subclass.
This commit is contained in:
Fischlurch 2023-10-10 21:45:41 +02:00
parent fad02bd00e
commit 42eba8425a
4 changed files with 165 additions and 166 deletions

View file

@ -60,6 +60,10 @@
** caller. Such threads *must* be joined however, and thus the destructor immediately
** terminates the application in case the thread is still running.
**
** A further variant ThreadHookable allows to attach user-provided callbacks invoked from
** the thread lifecycle; this can be used to build a thread-object that manages itself
** autonomously, or a thread that opens / closes interfaces tied to its lifecycle.
**
** ## Synchronisation
** The C++ standard provides that the end of the `std::thread` constructor _syncs-with_ the
** start of the new thread function, and likewise the end of the thread activity _syncs-with_
@ -148,6 +152,7 @@ namespace lib {
using lib::meta::typeSymbol;
using lib::meta::_Fun;
using util::isnil;
using std::function;
using std::forward;
using std::move;
@ -180,7 +185,7 @@ namespace lib {
{ }
ThreadWrapper (string const& threadID)
: threadID_{util::sanitise (threadID)}
: threadID_{isnil(threadID)? "sub-thread" : util::sanitise (threadID)}
, threadImpl_{} //Note: deliberately not starting the thread yet...
{ }
@ -264,38 +269,9 @@ namespace lib {
/**
* Thread Lifecycle Policy Extension:
* additionally self-manage the thread-wrapper allocation.
* @warning the thread-wrapper must have been heap-allocated.
*/
template<class BAS, class TAR>
struct PolicySelfManaged
: PolicyLaunchOnly<BAS>
{
using BasePol = PolicyLaunchOnly<BAS>;
using BasePol::BasePol;
void
handle_after_thread()
{
TAR* selfAllocation = static_cast<TAR*>(
static_cast<void*> (this));
if (BAS::isLive())
BAS::threadImpl_.detach();
delete selfAllocation;
}
void
handle_loose_thread()
{
ALERT (thread, "Self-managed thread was deleted from outside. Abort.");
}
};
/**
* Thread Lifecycle Policy Extension:
* additionally self-manage the thread-wrapper allocation.
* @warning the thread-wrapper must have been heap-allocated.
* invoke user-provided callbacks from within thread lifecycle.
* @see ThreadLifecycle::invokeThreadFunction for invocation...
* @see ThreadLifecycle::Launch for configuration of these hooks.
*/
template<class BAS, class TAR>
struct PolicyLifecycleHook
@ -501,7 +477,7 @@ namespace lib {
* @tparam FUN type of the function maintained in #PolicyLifecycleHook
* @note the user provided functor can take any type as argument, which
* is reachable by static cast from the thread-wrapper. Especially
* this allows both for low-level and userclass-internal hooks.
* this allows both for low-level and userclass-internal hooks.
*/
template<typename HOOK, class FUN>
auto
@ -539,7 +515,7 @@ namespace lib {
});
}
/** generic helper to add another »onion layer« to this config builder */
/** generic helper to add another »onion layer« to this config builder */
Launch&&
addLayer (Act action)
{
@ -617,6 +593,10 @@ namespace lib {
/************************************************************************//**
* A thin convenience wrapper to simplify thread-handling.
* The implementation is backed by the C++ standard library.
@ -631,7 +611,6 @@ namespace lib {
class Thread
: public thread::ThreadLifecycle<thread::PolicyLaunchOnly>
{
public:
using ThreadLifecycle::ThreadLifecycle;
@ -663,7 +642,6 @@ namespace lib {
: public thread::ThreadLifecycle<thread::PolicyResultJoin, RES>
{
using Impl = thread::ThreadLifecycle<thread::PolicyResultJoin, RES>;
public:
using Impl::Impl;
@ -717,34 +695,54 @@ namespace lib {
/************************************************************************//**
* Special configuration for a »fire-and-forget«-Thread.
* @internal this class is meant for subclassing. Start with #launchDetached()
* @tparam TAR the concrete type of the subclass to be started as autonomous,
* self-managed thread. Must be passed down since thread deletes itself.
/**
* Launch an autonomous self-managing thread (and forget about it).
* The thread-object is allocated to the heap and will delete itself on termination.
* @tparam TAR concrete type of the subclass to be started as autonomous detached thread.
* @param launchBuilder a flexible thread launch configuration to be used for starting;
* especially this contains the thread function and arguments to run in the thread.
* @note hooks `atExit` and `onOrphan` defined in the \a launchBuilder will be overridden.
* @remarks the `atExit` hook is the last piece of code executed within the thread; here it
* takes a pointer to the allocated instance of type \a TAR and deletes it from heap.
* Obviously this will invoke the destructor of the thread-wrapper eventually, at which
* point the `onOrphan` hook is invoked (since the thread is still running); at this point
* the C++ thread-handle is detached, so that invoking the dtor of std::thread will not
* terminate the system, rather just let the thread go away. The net result is an object
* of type \a TAR placed on the heap and kept there precisely as long as the thread runs.
*/
class ThreadAutonomous
: public thread::ThreadLifecycle<thread::PolicySelfManaged, ThreadAutonomous>
{
using Impl = thread::ThreadLifecycle<thread::PolicySelfManaged, ThreadAutonomous>;
public:
using Impl::Impl;
};
template<class TAR = ThreadHookable>
inline void
launchDetached (ThreadHookable::Launch&& launchBuilder)
{
static_assert (lib::meta::is_Subclass<TAR, ThreadHookable>());
new TAR{move(launchBuilder)
.atExit([](TAR& selfAllocation)
{
delete &selfAllocation;
})
.onOrphan([](thread::ThreadWrapper& wrapper)
{
if (wrapper.isLive())
wrapper.threadImpl_.detach();
})};
// Note: allocation tossed on the heap deliberately
} // The thread-function will pick up and manage *this
/**
* Launch an autonomous self-managing thread (and forget about it).
* The thread-wrapper is allocated to the heap and will delete itself on termination.
* @tparam TAR concrete type of the subclass to be started as autonomous detached thread.
* @param args a valid argument list to call the ctor of thread::ThreadLifecycle
*/
template<typename...INVO>
template<class TAR = ThreadHookable, typename...INVO>
inline void
launchDetached (INVO&& ...args)
launchDetached (string const& threadID, INVO&& ...args)
{
new ThreadAutonomous{forward<INVO> (args)...}; // Thread will pick up and manage *this
using Launch = typename TAR::Launch;
launchDetached<TAR> (Launch{forward<INVO> (args)...}
.threadID (threadID));
}
} // namespace lib
#endif /*LIB_THREAD_H*/

View file

@ -82,31 +82,34 @@ namespace test{
using Point = system_clock::time_point;
Point threadStart;
Point afterCtor;
// the new thread starts immediately from ctor-call...
Thread thread("lifecycle", [&]{
threadStart = system_clock::now();
});
afterCtor = system_clock::now();
CHECK (thread); // thread marked as running
while (thread) yield();
CHECK (not thread); // thread now marked as detached/dead
double offset = Dur{threadStart - afterCtor}.count();
SHOW_EXPR(offset)
CHECK (offset > 0);
}
} // Note: in practice we see here values > 100µs
// but in theory the thread might even overtake the launcher
/**
* @test verify a special setup to start a thread explicitly and to track
* the thread's lifecycle state.
* @test attach user provided callback hooks to the thread lifecycle.
*/
void
verifyThreadLifecycleHooks()
{
atomic_uint stage{0};
atomic_uint stage{0}; // flexible launch-builder syntax:
ThreadHookable thread{ThreadHookable::Launch([]{ sleep_for (5ms); })
.threadID("hooked thread")
.atStart([&]{ stage = 1; })
.atExit ([&]{ stage = 2; })};
.atExit ([&]{ stage = 2; })
.threadID("hooked thread")};
CHECK (thread);
CHECK (0 == stage);

View file

@ -388,12 +388,12 @@ namespace test {
auto fullCnt = work::Config::COMPUTATION_CAPACITY;
wof.activate (1.0);
sleep_for(1ms);
sleep_for(2ms);
CHECK (fullCnt == uniqueCnt);
CHECK (fullCnt == wof.size());
wof.activate (2.0);
sleep_for(1ms);
sleep_for(2ms);
CHECK (2*fullCnt == uniqueCnt);
CHECK (2*fullCnt == wof.size());
@ -401,11 +401,11 @@ namespace test {
CHECK (0 == wof.size());
uniqueCnt.clear();
sleep_for(1ms);
sleep_for(2ms);
CHECK (0 == uniqueCnt);
wof.activate (0.5);
sleep_for(1ms);
sleep_for(2ms);
CHECK (fullCnt/2 == uniqueCnt);
CHECK (fullCnt/2 == wof.size());
}

View file

@ -65012,7 +65012,7 @@
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1696468379848" ID="ID_1146069423" MODIFIED="1696541583707" TEXT="Erg&#xe4;nzung: autonomous Thread">
<linktarget COLOR="#bc3562" DESTINATION="ID_1146069423" ENDARROW="Default" ENDINCLINATION="444;909;" ID="Arrow_ID_516910789" SOURCE="ID_137837629" STARTARROW="None" STARTINCLINATION="-1280;-32;"/>
<icon BUILTIN="flag-yellow"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1696468398477" ID="ID_1775921981" MODIFIED="1696468422766" TEXT="neue Anforderung: komplett abgekoppelt">
<node COLOR="#435e98" CREATED="1696468398477" ID="ID_1775921981" MODIFIED="1696966299356" TEXT="neue Anforderung: komplett abgekoppelt">
<icon BUILTIN="yes"/>
<node CREATED="1696468424018" ID="ID_1127252428" MODIFIED="1696468584146" TEXT="ergibt sich aus dem Protokoll der C++14 - Threads">
<richcontent TYPE="NOTE"><html>
@ -65038,9 +65038,9 @@
<icon BUILTIN="messagebox_warning"/>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1696468596155" ID="ID_1909710868" MODIFIED="1696468616300" TEXT="Design: auf den neuen Thread-Wrapper aufsetzen">
<icon BUILTIN="flag-yellow"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1696468627430" ID="ID_1189676257" MODIFIED="1696468763145" TEXT="Anforderungen">
<node COLOR="#338800" CREATED="1696468596155" ID="ID_1909710868" MODIFIED="1696966286228" TEXT="Design: auf den neuen Thread-Wrapper aufsetzen">
<icon BUILTIN="button_ok"/>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1696468627430" ID="ID_1189676257" MODIFIED="1696966303504" TEXT="Anforderungen">
<icon BUILTIN="yes"/>
<node CREATED="1696468151894" ID="ID_1613034704" MODIFIED="1696468650111" TEXT="der Thread-Funktor mu&#xdf; das Thread-Objekt als selbst halten"/>
<node CREATED="1696468197640" ID="ID_1523718397" MODIFIED="1696468221818" TEXT="der Aufruf-context gibt jeden Bezug dazu auf"/>
@ -65115,7 +65115,7 @@
<icon BUILTIN="button_ok"/>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1696528863266" ID="ID_1924635467" MODIFIED="1696528890280" TEXT="soll aber sauberes Design sein">
<node COLOR="#435e98" CREATED="1696528863266" ID="ID_1924635467" MODIFIED="1696966145777" TEXT="soll aber sauberes Design sein">
<icon BUILTIN="yes"/>
<node CREATED="1696528894446" ID="ID_658666182" MODIFIED="1696528900161" TEXT="das hei&#xdf;t">
<node CREATED="1696528900773" ID="ID_1777061932" MODIFIED="1696528909994" TEXT="in das Policy-Schema integriert"/>
@ -65131,8 +65131,9 @@
</html></richcontent>
</node>
</node>
<node CREATED="1696529041064" ID="ID_922354226" MODIFIED="1696529055485" TEXT="L&#xf6;sungsansatz">
<node COLOR="#5b280f" CREATED="1696529056400" ID="ID_996247672" MODIFIED="1696529065639" TEXT="ein Wrapper um den Thread-Funktor">
<node CREATED="1696529041064" ID="ID_922354226" MODIFIED="1696966057189" TEXT="L&#xf6;sungsansatz">
<icon BUILTIN="info"/>
<node COLOR="#5b280f" CREATED="1696529056400" FOLDED="true" ID="ID_996247672" MODIFIED="1696966067068" TEXT="ein Wrapper um den Thread-Funktor">
<icon BUILTIN="button_cancel"/>
<node CREATED="1696529067175" ID="ID_1003871751" MODIFIED="1696529073338" TEXT="w&#xe4;re zwar besonders modular"/>
<node CREATED="1696529074075" ID="ID_1746987039" MODIFIED="1696529190075" TEXT="w&#xe4;re aber auch offensichtlich zus&#xe4;tzliche Komplexit&#xe4;t">
@ -65184,7 +65185,8 @@
</node>
</node>
</node>
<node CREATED="1696529645817" ID="ID_461966137" MODIFIED="1696529649845" TEXT="Varianten/Weiterungen">
<node COLOR="#435e98" CREATED="1696529645817" ID="ID_461966137" MODIFIED="1696966078558" TEXT="Varianten/Weiterungen">
<icon BUILTIN="list"/>
<node CREATED="1696529655008" ID="ID_1683255981" MODIFIED="1696529699438" TEXT="Variante-1 : self-managed">
<node CREATED="1696529705915" ID="ID_731698797" MODIFIED="1696532569698" TEXT="in der Policy liegt ein unique_ptr">
<richcontent TYPE="NOTE"><html>
@ -65251,9 +65253,7 @@
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1696898808050" ID="ID_649658845" MODIFIED="1696898912722" TEXT="w&#xe4;re potentiell gef&#xe4;hrlich">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
und zwar, sofern oben in der konkreten Subklasse irgendwo ein mix-in verwendet wird &#8212; in dem Fall m&#252;&#223;te n&#228;mlich der Pointer nachjustiert werden
@ -65267,17 +65267,13 @@
<icon BUILTIN="idea"/>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1696532299942" ID="ID_596357210" MODIFIED="1696898738780" TEXT="die jeweilige Front-End-Klasse nur in der Factory definieren">
<icon BUILTIN="yes"/>
</node>
</node>
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1696897248135" ID="ID_433063268" MODIFIED="1696897258683" TEXT="Subklassen erm&#xf6;glichen?">
<node COLOR="#5b280f" CREATED="1696897248135" ID="ID_433063268" MODIFIED="1696965815605" TEXT="Subklassen erm&#xf6;glichen?">
<icon BUILTIN="help"/>
<icon BUILTIN="button_cancel"/>
<node CREATED="1696897270002" ID="ID_944165024" MODIFIED="1696897420063">
<richcontent TYPE="NODE"><html>
<head>
</head>
<head/>
<body>
<p>
<i>ohne Subclassing</i>&#160;ist die ganze &#220;bung etwas &#252;berzogen
@ -65285,9 +65281,7 @@
</body>
</html></richcontent>
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
...es ist ja nett, da&#223; der Thread-Wrapper sich selbst verwaltet &#8212; und der ganze Aufwand blo&#223; f&#252;r zwei interne Datenfelder?&#160;&#160;w&#228;re da nicht ein &#187;workaround&#171; angemessener?
@ -65297,9 +65291,7 @@
</node>
<node CREATED="1696897426970" ID="ID_419436552" MODIFIED="1696898701788" TEXT="mit Subklasse wird aber das Front-End fragiler &#x2014; und beliebiger">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
wozu dann &#252;berhaupt noch das Front-End? Um einen etwas sonderbaren new-Aufruf einzupacken?
@ -65307,15 +65299,17 @@
</body>
</html></richcontent>
</node>
<node CREATED="1696897485658" ID="ID_885031549" MODIFIED="1696897505971" TEXT="Problem: mu&#xdf; die konkrete Klasse als Template-Parameter in die Policy einf&#xfc;hren">
<node COLOR="#5b280f" CREATED="1696897485658" ID="ID_885031549" MODIFIED="1696965757557" TEXT="Problem: mu&#xdf; die konkrete Klasse als Template-Parameter in die Policy einf&#xfc;hren">
<icon BUILTIN="messagebox_warning"/>
<icon BUILTIN="button_cancel"/>
<node CREATED="1696897535396" ID="ID_1827915916" MODIFIED="1696897641026" TEXT="das macht die ganze Kette ziemlich komplex"/>
<node CREATED="1696897641633" ID="ID_309942358" MODIFIED="1696897719398" TEXT="auch das Front-End braucht nun einen Template-Parameter"/>
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1696897720103" ID="ID_785903718" MODIFIED="1696898648512" TEXT="noch schlimmer: das verhindert Verwendung ohne Subclassing">
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1696897720103" ID="ID_785903718" MODIFIED="1696965765382" STYLE="fork" TEXT="noch schlimmer: das verhindert Verwendung ohne Subclassing">
<icon BUILTIN="stop-sign"/>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1696899336883" ID="ID_241659538" MODIFIED="1696899355344" TEXT="andere Idee: man k&#xf6;nnte nun Variante-1 auf Variante-2 zur&#xfc;ckf&#xfc;hren">
<node COLOR="#435e98" CREATED="1696899336883" ID="ID_241659538" MODIFIED="1696965889077" TEXT="andere Idee: man k&#xf6;nnte nun Variante-1 auf Variante-2 zur&#xfc;ckf&#xfc;hren">
<arrowlink COLOR="#ffffd1" DESTINATION="ID_1909867794" ENDARROW="Default" ENDINCLINATION="-11;-9;" ID="Arrow_ID_315230822" STARTARROW="None" STARTINCLINATION="-51;2;"/>
<icon BUILTIN="idea"/>
<node CREATED="1696899356785" ID="ID_1810857858" MODIFIED="1696899370834" TEXT="...und zwar weil Variante-1 jetzt ziemlich hohl geworden ist"/>
<node CREATED="1696899371359" ID="ID_204770506" MODIFIED="1696899384536" TEXT="im Besonderen wird gar keine spezielle Storage ben&#xf6;tigt"/>
@ -65324,9 +65318,7 @@
</node>
<node CREATED="1696899431703" ID="ID_804029707" MODIFIED="1696899484220" TEXT="...und dieser w&#xfc;rde eine ThreadLifecycle-Instanz als Argument bekommen">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
...und wir w&#228;ren aus der Nummer raus: das ist n&#228;mlich oberhalb der protected inheritance
@ -65336,6 +65328,24 @@
</node>
</node>
</node>
<node COLOR="#338800" CREATED="1696965775488" ID="ID_1909867794" MODIFIED="1696965923694">
<richcontent TYPE="NODE"><html>
<head/>
<body>
<p>
das ist die <i>viel elegantere </i>L&#246;sung: <u>Variante-1</u>&#160;durch <u>Variante-2</u>&#160; implemenitert
</p>
</body>
</html></richcontent>
<linktarget COLOR="#ffffd1" DESTINATION="ID_1909867794" ENDARROW="Default" ENDINCLINATION="-11;-9;" ID="Arrow_ID_315230822" SOURCE="ID_241659538" STARTARROW="None" STARTINCLINATION="-51;2;"/>
<icon BUILTIN="yes"/>
<node CREATED="1696965933149" ID="ID_1573026703" MODIFIED="1696965943299" TEXT="damit sind alle Probleme auf einmal erschlagen!"/>
<node CREATED="1696965943955" ID="ID_1421528010" MODIFIED="1696965960462" TEXT="der Code der Callbacks steht direkt neben dem &#xbb;freien&#xab; Heap-new"/>
<node CREATED="1696965962769" ID="ID_250643272" MODIFIED="1696965971748" TEXT="die down-cast ist nun sicher"/>
<node CREATED="1696965987578" ID="ID_1670280316" MODIFIED="1696965998650" TEXT="man kann beliebige Subtypen verwenden"/>
<node CREATED="1696965973496" ID="ID_1562329556" MODIFIED="1696965986393" TEXT="und eine sonderbare spezial-Policy f&#xe4;llt komplett weg"/>
<node CREATED="1696965999636" ID="ID_1837122164" MODIFIED="1696966015867" TEXT="es gibt keine spezielle Thread-Klasse mehr, die man &#xbb;nicht verwenden&#xab; soll"/>
</node>
</node>
<node CREATED="1696532404400" ID="ID_1917558827" MODIFIED="1696539443047" TEXT="Variante-2 : optional-Lifecycle">
<linktarget COLOR="#898bab" DESTINATION="ID_1917558827" ENDARROW="Default" ENDINCLINATION="-1027;99;" ID="Arrow_ID_1553665185" SOURCE="ID_104020495" STARTARROW="None" STARTINCLINATION="532;77;"/>
@ -65416,9 +65426,7 @@
</node>
<node CREATED="1696958235467" ID="ID_1922263135" MODIFIED="1696958334910">
<richcontent TYPE="NODE"><html>
<head>
</head>
<head/>
<body>
<p>
<i>ganz elegant </i>erst mal auf TheadLifecycle downcasten
@ -65426,9 +65434,7 @@
</body>
</html></richcontent>
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
was &#8222;rein zuf&#228;llig&#8220; hier in diesem nested scope in ThreadLifecycle erlaubt und auch sicher ist, denn hier haben wir noch Zugriff auf die protected geerbten Policy-Klassen...
@ -65440,7 +65446,8 @@
<node CREATED="1696958351770" ID="ID_174542726" MODIFIED="1696958368388" TEXT="den konkret vom gegebenen &#x3bb; erwarteten Argument-Typ verwenden"/>
</node>
</node>
<node CREATED="1696532838782" ID="ID_46766207" MODIFIED="1696532858447" TEXT="der Konflikt im Lebensdauer-Thema ist damit beigelegt">
<node COLOR="#338800" CREATED="1696532838782" ID="ID_46766207" MODIFIED="1696966093550" TEXT="der Konflikt im Lebensdauer-Thema ist damit beigelegt">
<icon BUILTIN="button_ok"/>
<node CREATED="1696532860011" ID="ID_132397075" MODIFIED="1696532867737" TEXT="bisher hatten wir hier einen Zielkonflikt"/>
<node CREATED="1696532868282" ID="ID_1051552803" MODIFIED="1696532889722" TEXT="indem nun die widersprechenden use-Cases explizit addressiert werden..."/>
<node CREATED="1696532890359" ID="ID_446007102" MODIFIED="1696533163041" TEXT="kann man hart auf den restriktiven default zur&#xfc;ckkehren">
@ -65465,15 +65472,13 @@
</node>
</node>
</node>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#ab1d25" CREATED="1696620911198" ID="ID_1727345298" MODIFIED="1696620937599" TEXT="Kritik (n&#xe4;chster Tag)">
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#ab1d25" CREATED="1696620911198" FOLDED="true" ID="ID_1727345298" MODIFIED="1696620937599" TEXT="Kritik (n&#xe4;chster Tag)">
<icon BUILTIN="stop-sign"/>
<node CREATED="1696620943304" ID="ID_211890661" MODIFIED="1696620971910" TEXT="gestern nur in fertigen Komponenten gedacht &#x2014; das war zu kurz gegriffen">
<icon BUILTIN="broken-line"/>
<node CREATED="1696620974692" ID="ID_408561702" MODIFIED="1696621055594" TEXT="jede der beiden Varianten impliziert eine abgeleitete Klasse">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
...sonst w&#228;re das ganze Unterfangen theoretischer Natur; nur dadurch wird es interessant, Storage zu verwalten und einen Zugang freizuschalten
@ -65494,7 +65499,7 @@
<node CREATED="1696621353177" ID="ID_1935311062" MODIFIED="1696621378012" TEXT="was ich aber dennoch unbedingt realisieren m&#xf6;chte: Ordnung der Lifecycle-Klammern">
<icon BUILTIN="yes"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1696621626749" ID="ID_1402437857" MODIFIED="1696621682930" TEXT="Konsequenz: callback-Hooks im Lifecycle bereitstellen">
<node COLOR="#435e98" CREATED="1696621626749" ID="ID_1402437857" MODIFIED="1696961415243" TEXT="Konsequenz: callback-Hooks im Lifecycle bereitstellen">
<icon BUILTIN="yes"/>
<node CREATED="1696621694652" ID="ID_489753305" MODIFIED="1696621702239" TEXT="das wirft Probleme auf...">
<node CREATED="1696621703203" ID="ID_1346123872" MODIFIED="1696621709128" TEXT="brauche daf&#xfc;r zus&#xe4;tzliche Storage"/>
@ -65509,9 +65514,7 @@
<node CREATED="1696623997956" ID="ID_801709365" MODIFIED="1696624021191" TEXT="und der Thread-Start steckt in der Basisklasse"/>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1696624455507" ID="ID_771623143" MODIFIED="1696640533961">
<richcontent TYPE="NODE"><html>
<head>
</head>
<head/>
<body>
<p>
&#10233;&#160;<i>Initialisierung</i>&#160;von Policy-Bausteinen <i>ist nicht m&#246;glich</i>
@ -65521,9 +65524,7 @@
<arrowlink COLOR="#fe225e" DESTINATION="ID_1852065850" ENDARROW="Default" ENDINCLINATION="147;-294;" ID="Arrow_ID_1803073395" STARTARROW="None" STARTINCLINATION="-332;18;"/>
<node CREATED="1696624710262" ID="ID_798050443" MODIFIED="1696624792744" TEXT="Konsequenz: ThreadJoinable ist (latent) racy">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
(seufz)
@ -65539,9 +65540,9 @@
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1696861323485" ID="ID_1893882898" MODIFIED="1696861419490" TEXT="mu&#xdf; flexible Konfiguration hierf&#xfc;r erm&#xf6;glichen">
<node COLOR="#338800" CREATED="1696861323485" ID="ID_1893882898" MODIFIED="1696961412982" TEXT="mu&#xdf; flexible Konfiguration hierf&#xfc;r erm&#xf6;glichen">
<arrowlink COLOR="#8184a8" DESTINATION="ID_997556571" ENDARROW="Default" ENDINCLINATION="-767;-772;" ID="Arrow_ID_1317755297" STARTARROW="None" STARTINCLINATION="-380;22;"/>
<icon BUILTIN="flag-yellow"/>
<icon BUILTIN="button_ok"/>
</node>
</node>
<node BACKGROUND_COLOR="#dec38f" COLOR="#990000" CREATED="1696628443151" ID="ID_1852065850" MODIFIED="1696861406605" TEXT="das Race-Problem stellt das ganze Design in Frage">
@ -65553,9 +65554,7 @@
</node>
<node CREATED="1696628634743" ID="ID_860811090" MODIFIED="1696639826869" TEXT="andererseits ist das Problem sehr wahrscheinlich theoretischer Natur">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
da erfahrungsgem&#228;&#223; der OS-Scheduler immer <i>eine gewisse</i>&#160;Latenz hat, bis ein Thread tats&#228;chlich ausf&#252;hrbar wird
@ -65573,9 +65572,7 @@
<node CREATED="1696639726816" ID="ID_1384372347" MODIFIED="1696639753848" TEXT="(i.d.R sehe ich sogar &#x2248; 500&#xb5;s)"/>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1696639754464" ID="ID_279169592" MODIFIED="1696639859888">
<richcontent TYPE="NODE"><html>
<head>
</head>
<head/>
<body>
<p>
und trotzdem: das ist <b>kein Gegenbeweis</b>
@ -65589,9 +65586,7 @@
</node>
<node CREATED="1696628756484" ID="ID_602079301" MODIFIED="1696629021008">
<richcontent TYPE="NODE"><html>
<head>
</head>
<head/>
<body>
<p>
man k&#246;nnte das Thema entsch&#228;rfen,
@ -65685,7 +65680,7 @@
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1696533317806" ID="ID_641021700" MODIFIED="1696533328356" TEXT="Sicherheit">
<node COLOR="#435e98" CREATED="1696533317806" ID="ID_641021700" MODIFIED="1696966141682" TEXT="Sicherheit">
<icon BUILTIN="yes"/>
<node CREATED="1696533340931" ID="ID_1317798504" MODIFIED="1696533569753" TEXT="Manipulations-Schutz &#x27f9; wird auf vern&#xfc;nftige Nutzung zur&#xfc;ckgef&#xfc;hrt">
<richcontent TYPE="NOTE"><html>
@ -65784,8 +65779,10 @@
<icon BUILTIN="yes"/>
</node>
</node>
<node CREATED="1696538580339" ID="ID_741763330" MODIFIED="1696538583740" TEXT="Implementierung">
<node CREATED="1696687299435" ID="ID_1271362386" MODIFIED="1696687306334" TEXT="Konfiguration erm&#xf6;glichen">
<node COLOR="#338800" CREATED="1696538580339" ID="ID_741763330" MODIFIED="1696966311070" TEXT="Implementierung">
<icon BUILTIN="button_ok"/>
<node COLOR="#338800" CREATED="1696687299435" ID="ID_1271362386" MODIFIED="1696961347895" TEXT="Konfiguration erm&#xf6;glichen">
<icon BUILTIN="button_ok"/>
<node COLOR="#5b280f" CREATED="1696687326411" ID="ID_682366843" MODIFIED="1696773642410" TEXT="BuilderQualfierSupport nutzbar machen">
<icon BUILTIN="button_cancel"/>
<node COLOR="#435e98" CREATED="1696687354848" FOLDED="true" ID="ID_1619359990" MODIFIED="1696860882593" TEXT="Einsatz kl&#xe4;ren">
@ -65836,15 +65833,13 @@
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1696773689915" ID="ID_505123094" MODIFIED="1696778498186" TEXT="dann bleibt wirklich nur noch ein Builder">
<icon BUILTIN="pencil"/>
<node COLOR="#338800" CREATED="1696773689915" FOLDED="true" ID="ID_505123094" MODIFIED="1696961344649" TEXT="Configuration-Builder ist die einzige L&#xf6;sung">
<icon BUILTIN="button_ok"/>
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1696773711584" ID="ID_1136655892" MODIFIED="1696773718472" TEXT="Alternativen?">
<icon BUILTIN="help"/>
<node CREATED="1696773722487" ID="ID_1069796427" MODIFIED="1696773786376">
<richcontent TYPE="NODE"><html>
<head>
</head>
<head/>
<body>
<p>
es <b>mu&#223;</b>&#160;ein Konstruktor-Aufruf sein
@ -65852,9 +65847,7 @@
</body>
</html></richcontent>
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
zwar k&#246;nnte man nun generell an eine Factory denken, aber diese verlagert die gesamten Gefahren mit dem Instance-Management auf den usage-Kontext, und untergr&#228;bt damit den Zweck des Unterfangens...
@ -65864,9 +65857,7 @@
</node>
<node CREATED="1696773788022" ID="ID_103067174" MODIFIED="1696773810341">
<richcontent TYPE="NODE"><html>
<head>
</head>
<head/>
<body>
<p>
er <b>soll</b>&#160;einfach und sprechend sein
@ -65877,9 +65868,7 @@
</node>
<node CREATED="1696773813191" ID="ID_921625697" MODIFIED="1696773886262">
<richcontent TYPE="NODE"><html>
<head>
</head>
<head/>
<body>
<p>
der Einstieg mu&#223; <b>zuverl&#228;ssig</b>&#160;im Typ verankert sein
@ -65890,9 +65879,7 @@
<node COLOR="#435e98" CREATED="1696773922124" ID="ID_310300656" MODIFIED="1696774335094" TEXT="&#x27f9; bleibt nur der Einstieg &#xfc;ber eine statische Methode im Zieltyp"/>
<node CREATED="1696773947217" ID="ID_897608956" MODIFIED="1696817454466">
<richcontent TYPE="NODE"><html>
<head>
</head>
<head/>
<body>
<p>
also....
@ -65926,14 +65913,12 @@
<icon BUILTIN="hourglass"/>
</node>
</node>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1696774572285" ID="ID_882374829" MODIFIED="1696799236893" TEXT="Zwiebelschalen-Design">
<icon BUILTIN="pencil"/>
<node COLOR="#338800" CREATED="1696774572285" ID="ID_882374829" MODIFIED="1696961281464" TEXT="Zwiebelschalen-Design">
<icon BUILTIN="button_ok"/>
<node CREATED="1696774580118" ID="ID_1750789171" MODIFIED="1696774597403" TEXT="der Builder ist ein tempor&#xe4;rer Typ (f&#xfc;r jeden aufruf spezifisch)"/>
<node CREATED="1696774626822" ID="ID_1811542479" MODIFIED="1696774694500">
<richcontent TYPE="NODE"><html>
<head>
</head>
<head/>
<body>
<p>
er bietet als internes API eine Funktion <font color="#5c403a" face="Monospaced"><b>configure(this)</b></font>
@ -65950,9 +65935,7 @@
<node CREATED="1696778568283" ID="ID_999434014" MODIFIED="1696778580090" TEXT="ich mu&#xdf; jetzt Funktor und Argumente in das &#x3bb; kopieren"/>
<node CREATED="1696778580835" ID="ID_1429363688" MODIFIED="1696778795182" TEXT="bekanntes Problem ohne einfache L&#xf6;sung">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
da bin ich schon x-mal dar&#252;ber gestolpert: man kann per Reference oder per Value initialisieren; was nicht funktioniert ist eine move-Initialisierung, d.h. jeder move-only Argument-Typ macht Probleme. Einziger Ausweg war f&#252;r mich bisher, die captures explizit zu benennen und per std::forward-assign zu initialisieren
@ -65970,9 +65953,7 @@
<node CREATED="1696812299764" ID="ID_166961627" MODIFIED="1696812330308" TEXT="und entlade das mit einer Hilfsfunktion in den std::thread-Konstruktor">
<node CREATED="1696812379266" ID="ID_870864473" MODIFIED="1696812462503" TEXT="ja... varargs &#x27f9; die Hilfsfunktion ist unvermeidlich">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
wenn halt Argument-Packs einfach als Typ repr&#228;sentierbar w&#228;ren &#8212; aber dem ist nicht so; man mu&#223; gegen ein getemplatetes Argument matchen, um aus einem Argument-Pack einen anderen Argument-Pack zu konstruieren
@ -66003,11 +65984,14 @@
<node BACKGROUND_COLOR="#d2beaf" COLOR="#5c4d6e" CREATED="1696860784996" ID="ID_997556571" MODIFIED="1696861419491" TEXT="spezielle Builder-Methoden">
<linktarget COLOR="#8184a8" DESTINATION="ID_997556571" ENDARROW="Default" ENDINCLINATION="-767;-772;" ID="Arrow_ID_1317755297" SOURCE="ID_1893882898" STARTARROW="None" STARTINCLINATION="-380;22;"/>
<icon BUILTIN="hourglass"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1696860795349" ID="ID_1603578610" MODIFIED="1696860801649" TEXT="atStart">
<icon BUILTIN="flag-yellow"/>
<node COLOR="#338800" CREATED="1696860795349" ID="ID_1603578610" MODIFIED="1696961291961" TEXT="atStart">
<icon BUILTIN="button_ok"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1696860798554" ID="ID_772861645" MODIFIED="1696860801650" TEXT="atEnd">
<icon BUILTIN="flag-yellow"/>
<node COLOR="#338800" CREATED="1696860798554" ID="ID_772861645" MODIFIED="1696961291535" TEXT="atExit">
<icon BUILTIN="button_ok"/>
</node>
<node COLOR="#338800" CREATED="1696961287137" ID="ID_1678356315" MODIFIED="1696961290790" TEXT="onOrphan">
<icon BUILTIN="button_ok"/>
</node>
<node BACKGROUND_COLOR="#d2beaf" COLOR="#5c4d6e" CREATED="1696860810473" ID="ID_1620627301" MODIFIED="1696860829244" TEXT="...more to follow...">
<font ITALIC="true" NAME="SansSerif" SIZE="10"/>
@ -66036,13 +66020,16 @@
</node>
</node>
</node>
<node CREATED="1696538593318" ID="ID_1072499488" MODIFIED="1696538606616" TEXT="neue Policies...">
<node COLOR="#338800" CREATED="1696538593318" ID="ID_1072499488" MODIFIED="1696961356753" TEXT="neue Policies...">
<icon BUILTIN="button_ok"/>
<node CREATED="1696538616428" ID="ID_203239471" MODIFIED="1696538652470" TEXT="spezialisieren beide auf PolicyLaunchOnly">
<icon BUILTIN="idea"/>
</node>
<node CREATED="1696538662293" ID="ID_612737461" MODIFIED="1696538713193" TEXT="Hooks verwenden">
<node COLOR="#338800" CREATED="1696538662293" ID="ID_612737461" MODIFIED="1696961361599" TEXT="Hooks verwenden">
<icon BUILTIN="button_ok"/>
<node CREATED="1696538729479" ID="ID_1821271950" MODIFIED="1696538732072" TEXT="handle_begin_thread"/>
<node CREATED="1696538713759" ID="ID_743139495" MODIFIED="1696538713759" TEXT="handle_after_thread"/>
<node CREATED="1696961378726" ID="ID_1213403952" MODIFIED="1696961379986" TEXT="handle_loose_thread"/>
</node>
<node CREATED="1696538607372" ID="ID_479618351" MODIFIED="1696538611095" TEXT="f&#xfc;r Variante-1">
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1696890808413" ID="ID_569216542" LINK="#ID_1183918146" MODIFIED="1696890916407" TEXT="es zeigt sich: ein smart-ptr l&#xf6;st das Problem gar nicht">
@ -66054,6 +66041,11 @@
<node CREATED="1696890851961" ID="ID_397553721" MODIFIED="1696890865991" TEXT="und auch kein pre-Hook; einfach sich selbst wegschie&#xdf;en und gut is">
<icon BUILTIN="ksmiletris"/>
</node>
<node COLOR="#5b280f" CREATED="1696966181262" ID="ID_1560538998" MODIFIED="1696966195315" TEXT="letztlich gar nicht mehr explizit zu implementieren">
<icon BUILTIN="button_cancel"/>
<node CREATED="1696966202593" ID="ID_315221853" MODIFIED="1696966230107" TEXT="Variante-2 erschl&#xe4;gt alles"/>
<node CREATED="1696966232300" ID="ID_607167636" MODIFIED="1696966249766" TEXT="nur spezielles front-End"/>
</node>
</node>
<node CREATED="1696538612261" ID="ID_661367597" MODIFIED="1696538614839" TEXT="f&#xfc;r Variante-2">
<node CREATED="1696933810166" ID="ID_906750178" MODIFIED="1696933829261" TEXT="stelle Storage bereit als std::function"/>
@ -66137,12 +66129,20 @@
<node CREATED="1696538743210" ID="ID_1370366397" MODIFIED="1696538750437" TEXT="Tests erg&#xe4;nzen">
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1696538756712" ID="ID_1688404846" MODIFIED="1696541608160" TEXT="ThreadWrapperAutonomous_test">
<icon BUILTIN="flag-yellow"/>
<node CREATED="1696539571988" ID="ID_791561993" MODIFIED="1696539592221" TEXT="demonstriert: einen Thread komplett abgekoppelt starten"/>
<node COLOR="#338800" CREATED="1696539571988" ID="ID_791561993" MODIFIED="1696966349054" TEXT="demonstriert: einen Thread komplett abgekoppelt starten">
<icon BUILTIN="button_ok"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1696966318864" ID="ID_1955344707" MODIFIED="1696966351181" TEXT="sauberes Memory-Management belegen">
<icon BUILTIN="flag-yellow"/>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1696538825003" ID="ID_1787030725" MODIFIED="1696539451332" TEXT="ThreadWrapperLifecycle_test">
<icon BUILTIN="flag-yellow"/>
<node CREATED="1696538968712" ID="ID_1296694941" MODIFIED="1696538983238" TEXT="sollte das Thema &#xbb;Lifecycle&#xab; insgesamt beleuchten"/>
<node CREATED="1696538984394" ID="ID_1424729205" MODIFIED="1696538993373" TEXT="die neue Variante ist dann nur ein Sonderfall"/>
<node COLOR="#338800" CREATED="1696966333429" ID="ID_232799934" MODIFIED="1696966344964" TEXT="Lifecycle-Hooks in Einsatz zeigen">
<icon BUILTIN="button_ok"/>
</node>
</node>
</node>
</node>
@ -95642,9 +95642,7 @@ class Something
<icon BUILTIN="messagebox_warning"/>
<node CREATED="1696859985804" ID="ID_798414043" MODIFIED="1696860302374" TEXT="23-10-09: JobPlanning_test">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
Einmal-Event beim Ausf&#252;hren der Testsuite nach Compile.