Library: policy for lifecycle hooks

after some further mulling over the design, it became clear that
a rather loose coupling to the actual usage scenario is preferrable.

Thus, instead of devising a fixed scheme how to reflect the thread state,
rather the usage can directly hook into some points in the thread lifecycle.
So this policy can be reduced to provide additional storage for functon objects.
This commit is contained in:
Fischlurch 2023-10-10 12:48:11 +02:00
parent 5f9683ef10
commit 578af05ebd
2 changed files with 148 additions and 13 deletions

View file

@ -214,9 +214,9 @@ namespace lib {
void waitGracePeriod() noexcept;
/* empty implementation for some policy methods */
void handle_begin_thread() { }
void handle_after_thread() { }
void handle_thread_still_running() { }
void handle_begin_thread() { } ///< called immediately at start of thread
void handle_after_thread() { } ///< called immediately before end of thread
void handle_loose_thread() { } ///< called when destroying wrapper on still running thread
};
@ -253,7 +253,7 @@ namespace lib {
}
void
handle_thread_still_running()
handle_loose_thread()
{
BAS::waitGracePeriod();
}
@ -283,13 +283,67 @@ namespace lib {
}
void
handle_thread_still_running()
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.
*/
template<class BAS, class TAR>
struct PolicyLifecycleHook
: PolicyLaunchOnly<BAS>
{
using BasePol = PolicyLaunchOnly<BAS>;
using BasePol::BasePol;
using Hook = function<void(TAR&)>;
Hook hook_beginThread{};
Hook hook_afterThread{};
Hook hook_looseThread{};
TAR&
castInstance()
{
return static_cast<TAR*>(
static_cast<void*> (this));
}
void
handle_begin_thread()
{
if (hook_beginThread)
hook_beginThread (castInstance());
else
BasePol::handle_begin_thread();
}
void
handle_after_thread()
{
if (hook_afterThread)
hook_afterThread (castInstance());
else
BasePol::handle_after_thread();
}
void
handle_loose_thread()
{
if (hook_looseThread)
hook_looseThread (castInstance());
else
BasePol::handle_loose_thread();
}
};
/**
* Thread Lifecycle Policy:
* - thread with the ability to publish results
@ -328,7 +382,7 @@ namespace lib {
}
void
handle_thread_still_running()
handle_loose_thread()
{
ALERT (thread, "Thread '%s' was not joined. Abort.", BAS::threadID_.c_str());
}
@ -360,7 +414,7 @@ namespace lib {
~ThreadLifecycle()
{
if (Policy::isLive())
Policy::handle_thread_still_running();
Policy::handle_loose_thread();
}
/** derived classes may create a disabled thread */
@ -423,6 +477,40 @@ namespace lib {
return move(*this);
}
template<typename HOOK>
Launch&&
atStart (HOOK&& hook)
{
return addHook (&Policy::hook_beginThread, forward<HOOK> (hook));
}
template<typename HOOK>
Launch&&
atEnd (HOOK&& hook)
{
return addHook (&Policy::hook_afterThread, forward<HOOK> (hook));
}
template<typename HOOK>
Launch&&
onOrphan (HOOK&& hook)
{
return addHook (&Policy::hook_looseThread, forward<HOOK> (hook));
}
private:
template<typename HOOK, class FUN>
Launch&&
addHook (FUN Policy::*storedHook, HOOK&& hook)
{
return addLayer ([storedHook, hook = forward<HOOK>(hook)]
(ThreadLifecycle& wrapper)
{
wrapper.*storedHook = move (hook);
chain (wrapper);
});
}
Launch&&
addLayer (Act action)
{

View file

@ -65206,6 +65206,7 @@
</node>
<node CREATED="1696529718984" ID="ID_1539716722" MODIFIED="1696529944892" TEXT="zus&#xe4;tzlichen Erweiterungspunkt nutzen">
<arrowlink COLOR="#fdfcc6" DESTINATION="ID_1373519021" ENDARROW="Default" ENDINCLINATION="-114;10;" ID="Arrow_ID_736802000" STARTARROW="None" STARTINCLINATION="116;8;"/>
<arrowlink COLOR="#fdfcc6" DESTINATION="ID_1004228427" ENDARROW="Default" ENDINCLINATION="-114;10;" ID="Arrow_ID_936715522" STARTARROW="None" STARTINCLINATION="116;8;"/>
<icon BUILTIN="idea"/>
</node>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1696529962087" ID="ID_683965677" MODIFIED="1696531663483" TEXT="ownership wird hier gekapert">
@ -65310,6 +65311,26 @@
<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">
<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"/>
<node CREATED="1696899394883" ID="ID_221270967" MODIFIED="1696899414119" TEXT="das hei&#xdf;t: das k&#xf6;nnte genausogut ein lifecycle-Hook machen">
<icon BUILTIN="idea"/>
</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>
<body>
<p>
...und wir w&#228;ren aus der Nummer raus: das ist n&#228;mlich oberhalb der protected inheritance
</p>
</body>
</html></richcontent>
</node>
</node>
</node>
</node>
<node CREATED="1696532404400" ID="ID_1917558827" MODIFIED="1696539443047" TEXT="Variante-2 : optional-Lifecycle">
@ -65326,8 +65347,8 @@
</body>
</html></richcontent>
</node>
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1696532676404" ID="ID_91266848" MODIFIED="1696624166370" TEXT="Front-End">
<icon BUILTIN="flag-pink"/>
<node COLOR="#5b280f" CREATED="1696532676404" ID="ID_91266848" MODIFIED="1696934197232" TEXT="Front-End">
<icon BUILTIN="button_cancel"/>
<node CREATED="1696532680835" ID="ID_553798887" MODIFIED="1696536376316">
<richcontent TYPE="NODE"><html>
<head/>
@ -65350,8 +65371,7 @@
</html></richcontent>
<icon BUILTIN="button_cancel"/>
</node>
</node>
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1696536837512" ID="ID_1958442975" MODIFIED="1696624184191" TEXT="Lebenszyklus-Zustand wird atomar verwaltet (acquire_release)">
<node COLOR="#5b280f" CREATED="1696536837512" ID="ID_1958442975" MODIFIED="1696934192282" TEXT="Lebenszyklus-Zustand wird atomar verwaltet (acquire_release)">
<richcontent TYPE="NOTE"><html>
<head/>
<body>
@ -65360,7 +65380,28 @@
</p>
</body>
</html></richcontent>
<icon BUILTIN="flag-pink"/>
<icon BUILTIN="button_cancel"/>
</node>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1696934162253" ID="ID_724180880" MODIFIED="1696934184964" STYLE="fork" TEXT="das f&#xfc;hrt zu starker Kopplung im Design">
<icon BUILTIN="stop-sign"/>
</node>
</node>
<node CREATED="1696934198943" ID="ID_737180308" MODIFIED="1696934210349" TEXT="besser: funktionale Erweiterungspunkte">
<node CREATED="1696934212695" ID="ID_1626568717" MODIFIED="1696934238138" TEXT="diese werden als std::function gespeichert"/>
<node CREATED="1696934261703" ID="ID_266607477" MODIFIED="1696934280168" TEXT="und aus entsprechenden Policy-hooks heraus aufgerufen"/>
<node CREATED="1696934280923" ID="ID_787857879" MODIFIED="1696934285592" TEXT="Hooks">
<node CREATED="1696529808620" ID="ID_78597801" MODIFIED="1696529832292" TEXT="umbenennen: &#x27fc; handle_after_thread"/>
<node CREATED="1696529836760" ID="ID_1004228427" MODIFIED="1696934402647" TEXT="zus&#xe4;tzlich: &#x27ff; handle_begin_thread">
<linktarget COLOR="#fdfcc6" DESTINATION="ID_1004228427" ENDARROW="Default" ENDINCLINATION="-114;10;" ID="Arrow_ID_936715522" SOURCE="ID_1539716722" STARTARROW="None" STARTINCLINATION="116;8;"/>
</node>
<node CREATED="1696529836760" ID="ID_1153306127" MODIFIED="1696934476853" TEXT="zus&#xe4;tzlich: &#x27ff; handle_loose_thread">
<linktarget COLOR="#fdfcc6" DESTINATION="ID_1153306127" ENDARROW="Default" ENDINCLINATION="-114;10;" ID="Arrow_ID_880044186" SOURCE="ID_1868637331" STARTARROW="None" STARTINCLINATION="263;12;"/>
<node CREATED="1696933886929" HGAP="25" ID="ID_796423082" MODIFIED="1696933932976" TEXT="(wird aufgerufen aus dem Destruktor &#x2014; falls der Thread noch l&#xe4;uft)" VSHIFT="7">
<font NAME="SansSerif" SIZE="11"/>
<icon BUILTIN="info"/>
</node>
</node>
</node>
</node>
</node>
<node CREATED="1696532838782" ID="ID_46766207" MODIFIED="1696532858447" TEXT="der Konflikt im Lebensdauer-Thema ist damit beigelegt">
@ -65978,7 +66019,13 @@
<icon BUILTIN="ksmiletris"/>
</node>
</node>
<node CREATED="1696538612261" ID="ID_661367597" MODIFIED="1696538614839" TEXT="f&#xfc;r Variante-2"/>
<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"/>
<node CREATED="1696529718984" ID="ID_1868637331" MODIFIED="1696934476853" TEXT="die schon definierten Hooks + zus&#xe4;tzlichen Erweiterungspunkt">
<arrowlink COLOR="#fdfcc6" DESTINATION="ID_1153306127" ENDARROW="Default" ENDINCLINATION="-114;10;" ID="Arrow_ID_880044186" STARTARROW="None" STARTINCLINATION="263;12;"/>
<icon BUILTIN="idea"/>
</node>
</node>
</node>
<node COLOR="#338800" CREATED="1696690988844" ID="ID_480585061" MODIFIED="1696861459249" TEXT="das Race-Problem addressieren">
<icon BUILTIN="button_ok"/>