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:
parent
fad02bd00e
commit
42eba8425a
4 changed files with 165 additions and 166 deletions
|
|
@ -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*/
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -65012,7 +65012,7 @@
|
|||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1696468379848" ID="ID_1146069423" MODIFIED="1696541583707" TEXT="Ergä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ß 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ß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ö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ö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äre zwar besonders modular"/>
|
||||
<node CREATED="1696529074075" ID="ID_1746987039" MODIFIED="1696529190075" TEXT="wäre aber auch offensichtlich zusätzliche Komplexitä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äre potentiell gefährlich">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
und zwar, sofern oben in der konkreten Subklasse irgendwo ein mix-in verwendet wird — in dem Fall müßte nä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öglichen?">
|
||||
<node COLOR="#5b280f" CREATED="1696897248135" ID="ID_433063268" MODIFIED="1696965815605" TEXT="Subklassen ermö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> ist die ganze Übung etwas überzogen
|
||||
|
|
@ -65285,9 +65281,7 @@
|
|||
</body>
|
||||
</html></richcontent>
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
...es ist ja nett, daß der Thread-Wrapper sich selbst verwaltet — und der ganze Aufwand bloß für zwei interne Datenfelder?  wäre da nicht ein »workaround« angemessener?
|
||||
|
|
@ -65297,9 +65291,7 @@
|
|||
</node>
|
||||
<node CREATED="1696897426970" ID="ID_419436552" MODIFIED="1696898701788" TEXT="mit Subklasse wird aber das Front-End fragiler — und beliebiger">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
wozu dann ü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ß die konkrete Klasse als Template-Parameter in die Policy einführen">
|
||||
<node COLOR="#5b280f" CREATED="1696897485658" ID="ID_885031549" MODIFIED="1696965757557" TEXT="Problem: muß die konkrete Klasse als Template-Parameter in die Policy einfü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önnte nun Variante-1 auf Variante-2 zurückführen">
|
||||
<node COLOR="#435e98" CREATED="1696899336883" ID="ID_241659538" MODIFIED="1696965889077" TEXT="andere Idee: man könnte nun Variante-1 auf Variante-2 zurückfü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ötigt"/>
|
||||
|
|
@ -65324,9 +65318,7 @@
|
|||
</node>
|
||||
<node CREATED="1696899431703" ID="ID_804029707" MODIFIED="1696899484220" TEXT="...und dieser würde eine ThreadLifecycle-Instanz als Argument bekommen">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
...und wir wären aus der Nummer raus: das ist nä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ösung: <u>Variante-1</u> durch <u>Variante-2</u>  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 »freien« 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ällt komplett weg"/>
|
||||
<node CREATED="1696965999636" ID="ID_1837122164" MODIFIED="1696966015867" TEXT="es gibt keine spezielle Thread-Klasse mehr, die man »nicht verwenden« 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 „rein zufällig“ 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 λ 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ückkehren">
|
||||
|
|
@ -65465,15 +65472,13 @@
|
|||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#ab1d25" CREATED="1696620911198" ID="ID_1727345298" MODIFIED="1696620937599" TEXT="Kritik (nächster Tag)">
|
||||
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#ab1d25" CREATED="1696620911198" FOLDED="true" ID="ID_1727345298" MODIFIED="1696620937599" TEXT="Kritik (nächster Tag)">
|
||||
<icon BUILTIN="stop-sign"/>
|
||||
<node CREATED="1696620943304" ID="ID_211890661" MODIFIED="1696620971910" TEXT="gestern nur in fertigen Komponenten gedacht — 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ä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ö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ür zusä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>
|
||||
⟹ <i>Initialisierung</i> von Policy-Bausteinen <i>ist nicht mö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ß flexible Konfiguration hierfür ermöglichen">
|
||||
<node COLOR="#338800" CREATED="1696861323485" ID="ID_1893882898" MODIFIED="1696961412982" TEXT="muß flexible Konfiguration hierfür ermö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äß der OS-Scheduler immer <i>eine gewisse</i> Latenz hat, bis ein Thread tatsächlich ausführbar wird
|
||||
|
|
@ -65573,9 +65572,7 @@
|
|||
<node CREATED="1696639726816" ID="ID_1384372347" MODIFIED="1696639753848" TEXT="(i.d.R sehe ich sogar ≈ 500µ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önnte das Thema entschä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 ⟹ wird auf vernünftige Nutzung zurückgefü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ö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ö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ä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ö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ß</b> ein Konstruktor-Aufruf sein
|
||||
|
|
@ -65852,9 +65847,7 @@
|
|||
</body>
|
||||
</html></richcontent>
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
zwar könnte man nun generell an eine Factory denken, aber diese verlagert die gesamten Gefahren mit dem Instance-Management auf den usage-Kontext, und untergrä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> 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ß <b>zuverlässig</b> im Typ verankert sein
|
||||
|
|
@ -65890,9 +65879,7 @@
|
|||
<node COLOR="#435e98" CREATED="1696773922124" ID="ID_310300656" MODIFIED="1696774335094" TEXT="⟹ bleibt nur der Einstieg ü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ärer Typ (fü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ß jetzt Funktor und Argumente in das λ kopieren"/>
|
||||
<node CREATED="1696778580835" ID="ID_1429363688" MODIFIED="1696778795182" TEXT="bekanntes Problem ohne einfache Lösung">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
da bin ich schon x-mal darü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ü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 ⟹ die Hilfsfunktion ist unvermeidlich">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
wenn halt Argument-Packs einfach als Typ repräsentierbar wären — aber dem ist nicht so; man muß 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ü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ö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ß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ä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ü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ä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 »Lifecycle« 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ühren der Testsuite nach Compile.
|
||||
|
|
|
|||
Loading…
Reference in a new issue