Library/Application: consolidate Monitor implementation

After the fundamental switch from POSIX to the C++14 wrappers
the existing implementation of the Monitor can now be drastically condensed,
removing several layers of indirection. Moreover, all signatures
shall be changed to blend in with the names and patterns established
by the C++ standard.

This is Step-1 : consolidate the Implementation.

(to ensure correctness, the existing API towards application code was retained)
This commit is contained in:
Fischlurch 2023-10-14 23:40:57 +02:00
parent c37871ca78
commit 73737f2aee
7 changed files with 536 additions and 152 deletions

View file

@ -64,8 +64,8 @@ namespace lib {
class ClassLock
: public Sync<CONF>::Lock
{
typedef typename Sync<CONF>::Lock Lock;
typedef typename sync::Monitor<CONF> Monitor;
using Lock = typename Sync<CONF>::Lock;
using Monitor = typename sync::Monitor<CONF>;
struct PerClassMonitor : Monitor {};
@ -80,7 +80,9 @@ namespace lib {
}
public:
ClassLock() : Lock (getPerClassMonitor()) { }
ClassLock()
: Lock{getPerClassMonitor()}
{ }
};

View file

@ -192,36 +192,37 @@ namespace lib {
template<class MTX>
class Condition
: public Mutex<Wrapped_Condition<MTX>>
struct Condition
: MTX
, std::condition_variable_any
{
typedef Wrapped_Condition<MTX> Cond;
public:
template<class PRED>
void
signal (bool wakeAll=false)
wait (PRED&& predicate)
{
if (wakeAll)
Cond::broadcast ();
else
Cond::signal ();
condVar().wait (mutex(), std::forward<PRED> (predicate));
}
/** @return `false` in case of timeout */
template<class BF>
/** @return `false` in case of timeout,
* `true` if predicate is fulfilled at return
*/
template<class REPR, class PERI, class PRED>
bool
wait (BF& predicate, uint timeout_ms =0)
wait_for (std::chrono::duration<REPR, PERI> const& timeout, PRED&& predicate)
{
while (not predicate())
if (timeout_ms != 0)
{
if (not Cond::timedwait (std::chrono::milliseconds (timeout_ms)))
return false;
}
else
Cond::wait ();
return true;
return condVar().wait_for (mutex(), timeout, std::forward<PRED> (predicate));
}
MTX&
mutex()
{
return static_cast<MTX&> (*this);
}
std::condition_variable_any&
condVar()
{
return static_cast<std::condition_variable_any&> (*this);
}
};
@ -263,41 +264,35 @@ namespace lib {
template<class IMPL>
class Monitor
: IMPL
, util::NonCopyable
{
public:
Monitor() {}
~Monitor() {}
/** allow copy, without interfering with the identity of IMPL */
Monitor (Monitor const& ref) : IMPL() { }
const Monitor& operator= (Monitor const& ref) { /*prevent assignment to base*/ return *this; }
void lock() { IMPL::lock(); }
void unlock() noexcept { IMPL::unlock(); }
void notify_one() noexcept { IMPL::notify_one(); }
void notify_all() noexcept { IMPL::notify_all(); }
void acquireLock() { IMPL::acquire(); }
void releaseLock() { IMPL::release(); }
void signal(bool a){ IMPL::signal(a); }
bool
wait (Flag flag, ulong timedwait_ms=0)
template<class PRED>
void
wait (PRED&& predicate)
{
BoolFlagPredicate checkFlag(flag);
return IMPL::wait(checkFlag, timedwait_ms);
IMPL::wait (std::forward<PRED>(predicate));
}
template<class X>
template<class DUR, class PRED>
bool
wait (X& instance, bool (X::*method)(void), ulong timedwait_ms=0) /////////////////////TICKET #1051 : add support for lambdas
wait_for (DUR const& timeout, PRED&& predicate)
{
BoolMethodPredicate<X> invokeMethod(instance, method); ///////////////////////TICKET #1057 : const correctness, allow use of const member functions
return IMPL::wait(invokeMethod, timedwait_ms);
return IMPL::wait_for (timeout, std::forward<PRED> (predicate));
}
};
typedef Mutex<Wrapped_ExclusiveMutex> NonrecursiveLock_NoWait;
typedef Mutex<Wrapped_RecursiveMutex> RecursiveLock_NoWait;
typedef Condition<Wrapped_ExclusiveMutex> NonrecursiveLock_Waitable;
typedef Condition<Wrapped_RecursiveMutex> RecursiveLock_Waitable;
using NonrecursiveLock_NoWait = std::mutex;
using RecursiveLock_NoWait = std::recursive_mutex;
using NonrecursiveLock_Waitable = Condition<std::mutex>;
using RecursiveLock_Waitable = Condition<std::recursive_mutex>;
} // namespace sync (helpers and building blocks)
@ -347,11 +342,11 @@ namespace lib {
template<class CONF = NonrecursiveLock_NoWait>
class Sync
{
typedef sync::Monitor<CONF> Monitor;
using Monitor = sync::Monitor<CONF>;
mutable Monitor objectMonitor_;
static Monitor&
getMonitor(const Sync* forThis)
getMonitor(Sync const* forThis)
{
REQUIRE (forThis);
return forThis->objectMonitor_;
@ -369,49 +364,62 @@ namespace lib {
public:
template<class X>
Lock(X* it) : mon_(getMonitor(it)){ mon_.acquireLock(); }
~Lock() { mon_.releaseLock(); }
Lock(X* it) : mon_(getMonitor(it)){ mon_.lock(); }
~Lock() { mon_.unlock(); }
void notify() { mon_.signal(false);}
void notifyAll() { mon_.signal(true); }
void notify() { mon_.notify_one(); }
void notifyAll() { mon_.notify_all(); }
template<typename C>
bool
wait (C& cond, ulong timeout=0) //////////////////////////////////////TICKET #1055 : accept std::chrono values here
wait (C&& cond, ulong timeout_ms=0) //////////////////////////////////////TICKET #1055 : accept std::chrono values here
{
return mon_.wait(cond,timeout);
if (timeout_ms)
return mon_.wait_for (std::chrono::milliseconds(timeout_ms)
,std::forward<C> (cond));
else
{
mon_.wait (std::forward<C> (cond));
return true;
}
}
template<typename X>
bool
wait (X& instance, bool (X::*predicate)(void), ulong timeout=0) //////////////////////TICKET #1051 : enable use of lambdas
wait (X& instance, bool (X::*predicate)(void), ulong timeout_ms=0) //////////////////////TICKET #1051 : enable use of lambdas
{
return mon_.wait(instance,predicate,timeout);
return wait([&]{ return (instance.*predicate)(); }, timeout_ms);
}
/** convenience shortcut:
* Locks and immediately enters wait state,
* observing a condition defined as member function.
* @deprecated WARNING this function is not correct! ////////////////////////////TICKET #1051
* Lock is not released on error from within wait()
* Lock is not released on error from within wait() /////TODO is actually fixed now; retain this API??
*/
template<class X>
Lock(X* it, bool (X::*method)(void))
: mon_(getMonitor(it))
{
mon_.acquireLock();
mon_.wait(*it,method);
mon_.lock();
try { wait(*it,method); }
catch(...)
{
mon_.unlock();
throw;
}
}
protected:
/** for creating a ClassLock */
Lock(Monitor& m) : mon_(m)
{ mon_.acquireLock(); }
Lock(Monitor& m)
: mon_(m)
{
mon_.lock();
}
/** for controlled access to the
* underlying sync primitives */
Monitor&
accessMonitor() { return mon_; }
/** subclass access to underlying sync primitives */
Monitor& accessMonitor() { return mon_; }
};
};

View file

@ -163,7 +163,7 @@ namespace control {
init_.sync(); // done with setup; loop may run now....
INFO (session, "Steam-Dispatcher running...");
{
Lock(this); // open public session interface:
Lock sync(this); // open public session interface:
commandService_.createInstance(*this);
}
}

View file

@ -75,7 +75,7 @@ namespace test{
auto start = system_clock::now();
bool salvation{false};
auto salvation = []{ return false; };
bool fulfilled = lock.wait (salvation, WAIT_mSec);
CHECK (not fulfilled); // condition not fulfilled, but timeout

View file

@ -32,9 +32,10 @@
#include "lib/sync.hpp"
#include <functional>
#include <atomic>
using std::bind;
using test::Test;
using std::atomic_bool;
namespace lib {
@ -73,14 +74,12 @@ namespace test{
public Sync<NonrecursiveLock_Waitable>
{
protected:
volatile bool got_new_data_;
atomic_bool got_new_data_{false};
public:
SyncOnBool() : got_new_data_ (false) {}
void getIt()
{
Lock(this).wait (got_new_data_);
Lock(this).wait ([this]{ return bool(got_new_data_); });
sum_ += input_;
}
@ -105,7 +104,7 @@ namespace test{
public:
void getIt()
{
Lock await(this, &SyncOnMemberPredicate::checkTheFlag);
Lock await(this, &SyncOnMemberPredicate::checkTheFlag); /////////////////////TODO becomes obsolete with the API change
sum_ += input_;
}
@ -158,8 +157,8 @@ namespace test{
{
typedef ThreadJoinable<> Thread; //////////////////////////////////////WIP
Thread ping ("SyncWaiting ping", bind (&Token::getIt, &tok));
Thread pong ("SyncWaiting pong", bind (&Token::getIt, &tok));
Thread ping ("SyncWaiting ping", [&]{ return tok.getIt(); });
Thread pong ("SyncWaiting pong", [&]{ return tok.getIt(); });
CHECK (ping);
CHECK (pong);

View file

@ -391,12 +391,12 @@ namespace test {
auto fullCnt = work::Config::COMPUTATION_CAPACITY;
wof.activate (1.0);
sleep_for(2ms);
sleep_for(5ms);
CHECK (fullCnt == uniqueCnt);
CHECK (fullCnt == wof.size());
wof.activate (2.0);
sleep_for(2ms);
sleep_for(5ms);
CHECK (2*fullCnt == uniqueCnt);
CHECK (2*fullCnt == wof.size());
@ -404,11 +404,11 @@ namespace test {
CHECK (0 == wof.size());
uniqueCnt.clear();
sleep_for(2ms);
sleep_for(5ms);
CHECK (0 == uniqueCnt);
wof.activate (0.5);
sleep_for(2ms);
sleep_for(5ms);
CHECK (fullCnt/2 == uniqueCnt);
CHECK (fullCnt/2 == wof.size());
}
@ -438,7 +438,8 @@ namespace test {
CHECK (3 == wof.size());
sleep_for(500ms); // ...sufficiently long to count way beyond 10'000
while (check < 6'000)
sleep_for(10ms); // .....sufficiently long to count way beyond 10'000
CHECK (check > 6'000);
CHECK (1 == wof.size());
}

View file

@ -65890,7 +65890,7 @@
</body>
</html></richcontent>
</node>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1696972878105" ID="ID_880873658" MODIFIED="1696972924189">
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1696972878105" FOLDED="true" ID="ID_880873658" MODIFIED="1697299089216">
<richcontent TYPE="NODE"><html>
<head/>
<body>
@ -65923,8 +65923,9 @@
</html></richcontent>
<icon BUILTIN="clanbomber"/>
</node>
<node COLOR="#435e98" CREATED="1696973047334" ID="ID_1485957927" MODIFIED="1696973196674" TEXT="Mitigation: nicht in die Thread-Funktion eintreten wenn nicht isAlive()">
<node COLOR="#5b280f" CREATED="1696973047334" FOLDED="true" ID="ID_1485957927" MODIFIED="1697298971369" TEXT="Mitigation: nicht in die Thread-Funktion eintreten wenn nicht isAlive()">
<icon BUILTIN="idea"/>
<icon BUILTIN="button_cancel"/>
<node CREATED="1696973209112" ID="ID_1135397788" MODIFIED="1696973227449" TEXT="die C++ Lib schlie&#xdf;t diesen Fall eigentlich aus"/>
<node CREATED="1696973227990" ID="ID_481018550" MODIFIED="1696976336073" TEXT="aber wenn jemand explizit detach() macht..."/>
<node CREATED="1696973241644" ID="ID_1093970050" MODIFIED="1696973309225" TEXT="eigentlich m&#xfc;&#xdf;te man diesen Fall auf einen &#xbb;Autonomous Thread&#xab; einschr&#xe4;nken">
@ -65937,6 +65938,17 @@
</body>
</html></richcontent>
</node>
<node BACKGROUND_COLOR="#e2b8ba" COLOR="#690f14" CREATED="1697298179939" ID="ID_439430070" LINK="#ID_141412141" MODIFIED="1697298970738" TEXT="Zu kurz gedacht: wirkt nicht wie gedacht &#x2014; und f&#xfc;hrt in anderen F&#xe4;llen zu Fehlverhalten">
<richcontent TYPE="NOTE"><html>
<head/>
<body>
<p>
Da bin ich einem Kurzschlu&#223; aufgesessen: wenn die Konstruktion scheitert, und der Destruktor (so wie hier) sich einfach auskoppelt, dann wird nichts im Wrapper selber gemacht, sondern dieser existiert nicht mehr. Der Thread greift damit wild auf freien Speicher zu, der zudem in keinster Weise synchronisiert ist (d.h. selbst wenn wir das Handle vorher auf 0 setzen, wird der schon startende Thread das wahrscheinlich nicht mehr mitbekommen). Dieses Synchronisations-Problem ist es aber auch, das zu <b>Fehlfunktionen</b>&#160;in anderen Konstellationen f&#252;hrt: es kommt sporadisch vor, da&#223; isLive() zu Beginn des Threads noch nicht wahr liefert; die Gr&#252;nde lie&#223;en sich nicht aufkl&#228;ren. In einem solchen Fall w&#252;rde der Thread spurlos terminieren &#8212; und dadurch an anderer Stelle m&#246;glichrweise ein Protokoll brechen oder einen Deadlock verursachen.
</p>
</body>
</html></richcontent>
<icon BUILTIN="stop-sign"/>
</node>
</node>
</node>
</node>
@ -66353,8 +66365,8 @@
<icon BUILTIN="yes"/>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1696538432819" ID="ID_1257702273" MODIFIED="1696538500747" TEXT="Analyse der Semantik">
<icon BUILTIN="flag-yellow"/>
<node COLOR="#338800" CREATED="1696538432819" ID="ID_1257702273" MODIFIED="1697321899332" TEXT="Analyse der Semantik">
<icon BUILTIN="button_ok"/>
<node CREATED="1696538453264" ID="ID_1672358651" MODIFIED="1696538455260" TEXT="POSIX">
<node CREATED="1696538464327" ID="ID_1024694040" MODIFIED="1696538476389" TEXT="ich hatte schon einen Basis-Adapter dazwischen">
<icon BUILTIN="idea"/>
@ -66421,16 +66433,13 @@
<node CREATED="1697211296788" ID="ID_516008091" MODIFIED="1697211306007" TEXT="nein: das hilft nicht"/>
<node CREATED="1697211306619" ID="ID_20444784" MODIFIED="1697211430279" TEXT="unique_lock kann selber nicht rekursiv assoziiert werden">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
Es kann zwar ein rekursives Mutex verwenden, aber jede Ebene von Locking mu&#223; dann als eigenes unique_lock-Token repr&#228;sentiert werden.
</p>
</body>
</html>
</richcontent>
</html></richcontent>
</node>
<node CREATED="1697211431074" ID="ID_921453654" MODIFIED="1697211474012" TEXT="&#x27f9; unique_lock kann daher nicht gemeinsam mit mehreren Threads arbeiten"/>
</node>
@ -66438,74 +66447,68 @@
<icon BUILTIN="idea"/>
<node CREATED="1697211738347" ID="ID_1470675670" MODIFIED="1697211757821">
<richcontent TYPE="NODE"><html>
<head>
</head>
<head/>
<body>
<p>
diese setzt nur ein <i>BasicLockable</i>&#160;voraus
</p>
</body>
</html>
</richcontent>
</html></richcontent>
</node>
<node CREATED="1697211758557" ID="ID_1308356052" MODIFIED="1697211769888">
<richcontent TYPE="NODE"><html>
<head>
</head>
<head/>
<body>
<p>
Mutex selber ist bereits <i>BasicLockable</i>
</p>
</body>
</html>
</richcontent>
</html></richcontent>
</node>
</node>
</node>
<node CREATED="1697153008914" ID="ID_939982348" MODIFIED="1697153033086" TEXT="keine Error-R&#xfc;ckgabecodes mehr. Stattdessen throw std::system_error"/>
<node COLOR="#435e98" CREATED="1697208294038" ID="ID_724408266" MODIFIED="1697208642249">
<richcontent TYPE="NODE"><html>
<head>
</head>
<head/>
<body>
<p>
die C++ - Wrapper sind <b>non-copyable</b>
</p>
</body>
</html>
</richcontent>
</html></richcontent>
<icon BUILTIN="messagebox_warning"/>
<node CREATED="1697208611826" ID="ID_1407647722" MODIFIED="1697226243538" TEXT="was man synchronisiert, hat typischerweise Referenz-Semantik">
<icon BUILTIN="idea"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1697208590782" ID="ID_1383871199" MODIFIED="1697226552108" TEXT="aber: class Monitor erlaubt Brechen dieser Bedingung">
<linktarget COLOR="#c36885" DESTINATION="ID_1383871199" ENDARROW="Default" ENDINCLINATION="-768;38;" ID="Arrow_ID_1367033811" SOURCE="ID_1311077272" STARTARROW="None" STARTINCLINATION="-220;-13;"/>
<node COLOR="#435e98" CREATED="1697208590782" FOLDED="true" ID="ID_1383871199" MODIFIED="1697301734198" TEXT="aber: class Monitor erlaubt Brechen dieser Bedingung">
<linktarget COLOR="#7168c3" DESTINATION="ID_1383871199" ENDARROW="Default" ENDINCLINATION="-768;38;" ID="Arrow_ID_1367033811" SOURCE="ID_1311077272" STARTARROW="None" STARTINCLINATION="-220;-13;"/>
<icon BUILTIN="broken-line"/>
<node CREATED="1697226328908" ID="ID_1205179392" MODIFIED="1697226343430" TEXT="er hat einen Copy-Konstruktor und Assignment"/>
<node CREATED="1697226345928" ID="ID_244225602" MODIFIED="1697226360003" TEXT="diese erzeugen jeweils einfach eine neue Implementierung"/>
<node CREATED="1697226360536" ID="ID_1800556938" MODIFIED="1697226426877" TEXT="nicht die feine englische Art">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
...gegebenfalls kann es dadurch passieren, da&#223; man ein grade gesperrtes Mutex einfach &#8222;fahren l&#228;&#223;t&#8220; &#8212; mit unabsehbaren Folgen
</p>
</body>
</html>
</richcontent>
</html></richcontent>
<font ITALIC="true" NAME="SansSerif" SIZE="12"/>
</node>
<node COLOR="#338800" CREATED="1697301705066" ID="ID_249445320" MODIFIED="1697301728385" TEXT="weg damit">
<icon BUILTIN="yes"/>
</node>
</node>
<node COLOR="#338800" CREATED="1697301688052" ID="ID_1729479673" MODIFIED="1697301694299" TEXT="stellt sich aber als irrelevant heraus">
<icon BUILTIN="button_ok"/>
</node>
</node>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1697153970230" ID="ID_1218189224" MODIFIED="1697153991860" TEXT="Herangehensweise?">
<node COLOR="#435e98" CREATED="1697153970230" ID="ID_1218189224" MODIFIED="1697321893506" TEXT="Herangehensweise?">
<icon BUILTIN="help"/>
<node CREATED="1697153994987" ID="ID_678749516" MODIFIED="1697153998214" TEXT="Situation">
<node CREATED="1697153999066" ID="ID_1857771089" MODIFIED="1697154022235" TEXT="ich habe ein relativ koh&#xe4;sives St&#xfc;ck Code mit einem schmalen API nach au&#xdf;en"/>
@ -66513,9 +66516,7 @@
<node CREATED="1697154093695" ID="ID_680368704" MODIFIED="1697154108078" TEXT="der Code ist sehr gut gegliedert; es gibt einen low-Level-Layer"/>
<node CREATED="1697154131456" ID="ID_1645036069" MODIFIED="1697154252320" TEXT="der Code orientiert sich an POSIX &#x27f9; er ist Konventions-orientiert">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
Genauer gesagt, der Code versucht, die Konventions-basierte Herangehensweise aus POSIX / C in einen Token-orientierten Ansatz f&#252;r C++ zu &#252;bersetzen. Das bedeutet aber, auch das Monitor-API ist noch Konventions-basiert
@ -66555,9 +66556,7 @@
<node CREATED="1697156412448" ID="ID_659475954" MODIFIED="1697156527005" TEXT="das Ergebnis ist offen f&#xfc;r &#x201e;wilden&#x201c; Direkt-Gebrauch">
<node CREATED="1697156532544" ID="ID_273574678" MODIFIED="1697156637966" TEXT="denn urspr&#xfc;nglich war das sogar die Intention">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
Ganz am Anfang hatte ich die Makros aus NoBug, deren Gebrauch im C++-Code schwierig ist. Daher dachte ich, ich packe die jeweils in einen Wrapper. Der Monitor ist dann nur ein Zustatz-Feature
@ -66567,9 +66566,7 @@
</node>
<node CREATED="1697156544607" ID="ID_1900999328" MODIFIED="1697156780356" TEXT="solcher Gebrauch ist dann aber in der Praxis bisher nie notwendig gewesen">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
...aber nachdem ich den Monitor entwickelt hatte, war mir klar, da&#223; ich an den Basis-Elementen gar kein Interesse mehr habe, weil der Monitor ein Design-Pattern ist und damit ordnend auf den Code wirkt. Im Lauf der Jahre hat sich dann gezeigt, da&#223; ich &#252;berhaupt nichts anderes brauche, als nur das Lock-Guard front-End (+Atomics f&#252;r alle nicht-trivialen F&#228;lle).
@ -66587,9 +66584,7 @@
<node CREATED="1697156976195" ID="ID_681854744" MODIFIED="1697156985008" TEXT="deshalb kann auch alles Andere zur&#xfc;ckgebaut werden"/>
<node CREATED="1697157070044" ID="ID_1501146985" MODIFIED="1697157223059" TEXT="die unique_lock-Instanz ist zugleich Verbesserung und zus&#xe4;tzlicher Ballast">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
Verbesserung, weil sie die Implementierung einfach und klar macht, und mehr dem C++-Stil entspricht. Aber sie ist auch ein stets vorhandener zus&#228;tzlicher Storage-Ballast, der eigentlich nicht notwendig w&#228;re
@ -66613,9 +66608,7 @@
<node CREATED="1697157519076" ID="ID_319583115" MODIFIED="1697157532140" TEXT="es handelt sich nicht um Alternativen, sondern einen Stufen-Plan"/>
<node CREATED="1697157566462" ID="ID_652673137" MODIFIED="1697157722839" TEXT="zur Vermeidung von Entwicklungs-Risiken sollten alle Schritte durchlaufen werden">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
zwar traue ich mir zu, die mittlere Stufe der &#187;strukturellen Verbesserung&#171; direkt zu implementieren, aber in dieser Hinsicht &#252;bersch&#228;tze ich h&#228;ufig die reale Komplexit&#228;t und die Projekt-Risiken. Schon allein um aufwendige Regressionen zu vermeiden sollte stets auf gute Test-Coverage geachtet werden, was nurch durch schritweises Vorgehen m&#246;glich ist
@ -66629,8 +66622,8 @@
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1696538492114" ID="ID_1214186481" MODIFIED="1696538497123" TEXT="Umarbeiten">
<icon BUILTIN="flag-yellow"/>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1697208267170" ID="ID_1417792791" MODIFIED="1697208273283" TEXT="Stufe-1">
<icon BUILTIN="pencil"/>
<node COLOR="#338800" CREATED="1697208267170" ID="ID_1417792791" MODIFIED="1697321886529" TEXT="Stufe-1">
<icon BUILTIN="button_ok"/>
<node CREATED="1697211709960" ID="ID_1334084058" MODIFIED="1697211722231" TEXT="mutex, shared_mutex und condition_var_any einf&#xfc;hren"/>
<node CREATED="1697212577546" ID="ID_701908821" MODIFIED="1697212604297" TEXT="elementare Wait-Logik in wrapped_condition nachbauen">
<node CREATED="1697212819465" ID="ID_1989441029" MODIFIED="1697212843810" TEXT="die Timeout-Flag wird hintenrum durch lumiera_lockerror hochgegeben">
@ -66648,16 +66641,13 @@
<node CREATED="1697227176603" ID="ID_1461108141" MODIFIED="1697227196532" TEXT="er kann im Emergency-Fall nachtr&#xe4;glich ein Timeout setzen"/>
<node CREATED="1697227368355" ID="ID_8720299" MODIFIED="1697227492130" TEXT="vermeidet Deadlock mit nur einem Thread">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
...zumindest war das wohl die Motivation, wenn ich die Kommentare im Test hinzunehme.
</p>
</body>
</html>
</richcontent>
</html></richcontent>
</node>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1697227493003" ID="ID_1899195103" MODIFIED="1697227520087" TEXT="erscheint mir halbgar">
<icon BUILTIN="smiley-angry"/>
@ -66668,16 +66658,373 @@
</node>
</node>
</node>
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1697226501663" ID="ID_1038438154" MODIFIED="1697226512124" TEXT="Problem Kopierbarkeit">
<icon BUILTIN="flag-pink"/>
<node COLOR="#338800" CREATED="1697226501663" ID="ID_1038438154" MODIFIED="1697321884423" TEXT="Problem Kopierbarkeit">
<icon BUILTIN="button_ok"/>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1697226517446" ID="ID_1311077272" MODIFIED="1697226570220" TEXT="Monitor hat das Problem bisher verborgen">
<arrowlink COLOR="#c36885" DESTINATION="ID_1383871199" ENDARROW="Default" ENDINCLINATION="-768;38;" ID="Arrow_ID_1367033811" STARTARROW="None" STARTINCLINATION="-220;-13;"/>
<arrowlink COLOR="#7168c3" DESTINATION="ID_1383871199" ENDARROW="Default" ENDINCLINATION="-768;38;" ID="Arrow_ID_1367033811" STARTARROW="None" STARTINCLINATION="-220;-13;"/>
<icon BUILTIN="info"/>
</node>
<node CREATED="1697301758212" ID="ID_1983338613" MODIFIED="1697301848459" TEXT="Sync sollte nicht kopierbar sein">
<richcontent TYPE="NOTE"><html>
<head/>
<body>
<p>
rein konzeptionell sollte ein synchronisierbares Objekt nicht kopierbar sein, schon allein weil sich dadurch der Status der gemeinsamen Nutzbarkeit verwischt
</p>
</body>
</html></richcontent>
</node>
<node COLOR="#338800" CREATED="1697301861004" ID="ID_153945609" MODIFIED="1697315802188" TEXT="Monitor non-copyalbe">
<icon BUILTIN="button_ok"/>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1697238392317" ID="ID_785406259" MODIFIED="1697238398404" TEXT="Stufe-2">
</node>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1697238392317" ID="ID_785406259" MODIFIED="1697321911701" TEXT="Stufe-2">
<icon BUILTIN="pencil"/>
<node COLOR="#338800" CREATED="1697315816914" ID="ID_1924043938" MODIFIED="1697315839198" TEXT="Implementierung in eine einzige Policy-Klasse">
<icon BUILTIN="button_ok"/>
<node COLOR="#338800" CREATED="1697315846032" ID="ID_1084339407" MODIFIED="1697321834835" TEXT="direkt von den Wrappern erben">
<icon BUILTIN="button_ok"/>
</node>
<node COLOR="#338800" CREATED="1697315859207" ID="ID_735098743" MODIFIED="1697321831696" TEXT="Namen/Signaturen an C++ anpassen">
<icon BUILTIN="button_ok"/>
<node CREATED="1697315946757" ID="ID_1745363491" MODIFIED="1697315950887" TEXT="lock / unlock"/>
<node CREATED="1697315951457" ID="ID_1757955784" MODIFIED="1697315957631" TEXT="wait / wait_for"/>
<node CREATED="1697315958179" ID="ID_1463728870" MODIFIED="1697315962775" TEXT="std::chrono-Argument"/>
<node CREATED="1697318219189" ID="ID_1715699621" MODIFIED="1697318225992" TEXT="notify_one | notify_all">
<node CREATED="1697318228429" ID="ID_85018579" MODIFIED="1697318237200" TEXT="da sind die neuen Namen wirklich besser"/>
<node CREATED="1697318237762" ID="ID_178110028" MODIFIED="1697318254517" TEXT="und die Trennung ist ebenfalls vorzuzuziehen"/>
</node>
</node>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1697318278751" ID="ID_986327606" MODIFIED="1697321837879" TEXT="wait-API vereinheitlichen">
<icon BUILTIN="pencil"/>
<node CREATED="1697318295168" ID="ID_1779444313" MODIFIED="1697321848775" TEXT="das Timeout-Feature wird (wie erwartet) nur selten genutzt">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
daher erscheint es sinnvoll
</p>
<ul>
<li>
diese seltenen F&#228;lle als separate Methode herauszuf&#252;hren
</li>
<li>
die Signatur komplett an C++ anzupassen
</li>
</ul>
</body>
</html>
</richcontent>
<arrowlink COLOR="#6879a1" DESTINATION="ID_620668033" ENDARROW="Default" ENDINCLINATION="8;-31;" ID="Arrow_ID_542802268" STARTARROW="None" STARTINCLINATION="-148;7;"/>
</node>
<node COLOR="#338800" CREATED="1697318385528" ID="ID_1149590819" MODIFIED="1697318406151" TEXT="den nachtr&#xe4;glich setzbaren Timeout schaffe ich ab">
<icon BUILTIN="yes"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1697318411673" ID="ID_1823152866" MODIFIED="1697321858569" TEXT="besserer Funktor-Support">
<icon BUILTIN="yes"/>
<node CREATED="1697319813178" ID="ID_939382602" MODIFIED="1697319816230" TEXT="F&#xe4;lle">
<node CREATED="1697318513548" ID="ID_1134079993" MODIFIED="1697318618743" TEXT="allgemeiner Funktor bool(void)">
<node CREATED="1697318602298" ID="ID_1305749510" MODIFIED="1697318609292" TEXT="das ist der Haupt-Eingang"/>
<node CREATED="1697318609864" ID="ID_1803337240" MODIFIED="1697318617563" TEXT="alle anderen werden darauf zur&#xfc;ckgef&#xfc;hrt"/>
</node>
<node CREATED="1697318499319" ID="ID_1385588809" MODIFIED="1697318512954" TEXT="Member-Funktion des Monitor-Tr&#xe4;gers">
<node CREATED="1697318580841" ID="ID_1410594297" MODIFIED="1697318588414" TEXT="kann nur auf dem Guard realisiert werden"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1697323173068" ID="ID_1950494758" MODIFIED="1697327262001" TEXT="Problem: der this-Pointer ist nur im Lock-ctor bekannt">
<arrowlink COLOR="#b16c50" DESTINATION="ID_420557101" ENDARROW="Default" ENDINCLINATION="667;0;" ID="Arrow_ID_1731288409" STARTARROW="None" STARTINCLINATION="172;9;"/>
<icon BUILTIN="messagebox_warning"/>
</node>
</node>
<node CREATED="1697318531847" ID="ID_127095654" MODIFIED="1697318579016" TEXT="Referenz auf etwas bool-Konvertierbares">
<node CREATED="1697318671961" ID="ID_557138075" MODIFIED="1697318690658" TEXT="intuitiv einfach aber technisch schwierig"/>
<node CREATED="1697318723114" ID="ID_50273287" MODIFIED="1697318732265" TEXT="brauche wohl einen enable-if-Helper">
<node CREATED="1697320210624" ID="ID_941432569" MODIFIED="1697320292946" TEXT="es gen&#xfc;gt, die Referenz per Signatur zu erzwingen">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
Hier gibt es zwar eine L&#252;cke, n&#228;mlich die const&amp; auf einen rvalue &#8212; aber das hier ist keine general-purpose-Library!
</p>
</body>
</html>
</richcontent>
</node>
<node CREATED="1697320296110" ID="ID_393798254" MODIFIED="1697320326400" TEXT="Hauptproblem ist, das kompakt im Code darzustellen">
<icon BUILTIN="messagebox_warning"/>
</node>
</node>
</node>
</node>
<node CREATED="1697319828481" ID="ID_245082806" MODIFIED="1697319861973" TEXT="sollte kombinatorische Explosion vermeiden">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
also entweder ganz oben oder ganz unten, und ansonsten nur noch einen Template-Parameter durchgeben
</p>
</body>
</html>
</richcontent>
<icon BUILTIN="yes"/>
</node>
<node COLOR="#5b280f" CREATED="1697319863019" ID="ID_122504390" MODIFIED="1697327099006" TEXT="wegen Member-Funktion: mu&#xdf; im Guard behandelt werden">
<linktarget COLOR="#c12834" DESTINATION="ID_122504390" ENDARROW="Default" ENDINCLINATION="-5;64;" ID="Arrow_ID_234610428" SOURCE="ID_1582251486" STARTARROW="None" STARTINCLINATION="-330;-9;"/>
<icon BUILTIN="button_cancel"/>
<node CREATED="1697319898631" ID="ID_859529089" MODIFIED="1697320109488" TEXT="dann Satz &#xfc;berladener Template-Funktionen">
<icon BUILTIN="idea"/>
</node>
<node COLOR="#435e98" CREATED="1697319960874" ID="ID_317811010" MODIFIED="1697327037668" TEXT="die Member-Funktion ist aufgrund der speziellen Signatur unproblematisch">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
man mu&#223; nicht speziell auf den Typ des Tr&#228;gers abstellen; vielmehr kann man dann einen static-cast nachschalten, und der scheitert dann halt gegebenfalls beim Bauen. Das habe ich grade eben genauso beim neuen Thread-Wrapper gemacht, und es hat sich bisher gut bew&#228;hrt. Spezielle static-asserts sind dann gar nicht notwendig
</p>
</body>
</html>
</richcontent>
</node>
</node>
<node COLOR="#435e98" CREATED="1697325938478" ID="ID_230563569" MODIFIED="1697326972528" TEXT="Zweifel: ist es dann &#xfc;berhaupt sinnvoll, Member-Pr&#xe4;dikate speziell zu unterst&#xfc;tzen?">
<icon BUILTIN="help"/>
<node CREATED="1697326582105" ID="ID_1184603595" MODIFIED="1697326597675" TEXT="denn die Situation ist...">
<node CREATED="1697326598743" ID="ID_28762827" MODIFIED="1697326670280" TEXT="wir k&#xf6;nnen sie nur in einem Spezial-Konstruktor direkt unterst&#xfc;tzen">
<arrowlink COLOR="#9f5f73" DESTINATION="ID_420557101" ENDARROW="None" ENDINCLINATION="231;-36;" ID="Arrow_ID_1797357140" STARTARROW="Default" STARTINCLINATION="-262;11;"/>
</node>
<node CREATED="1697326707584" ID="ID_1941844220" MODIFIED="1697326728051">
<richcontent TYPE="NODE"><html>
<head>
</head>
<body>
<p>
man h&#228;tte dann also zwei verschiedene APIs f&#252;r <i>essentiell das Gleiche</i>
</p>
</body>
</html>
</richcontent>
</node>
<node CREATED="1697326681404" ID="ID_88758521" MODIFIED="1697326701517" TEXT="andererseits ist durch die Lambdas eine generische L&#xf6;sung gegeben"/>
<node CREATED="1697326743932" ID="ID_956630359" MODIFIED="1697326921888" TEXT="...und diese ist nahezu genauso kompakt">
<node CREATED="1697326763018" ID="ID_25024903" MODIFIED="1697326821669" TEXT="Lock sync{this, &amp;MyClass::predicate}"/>
<node CREATED="1697326825569" ID="ID_1892485138" MODIFIED="1697326884997" TEXT="Lock sync{this, [&amp;]{ return predicate(); }}"/>
</node>
</node>
<node BACKGROUND_COLOR="#ccb59b" COLOR="#6e2a38" CREATED="1697326947256" ID="ID_1582251486" MODIFIED="1697327107741" TEXT="Beschlu&#xdf;: Support f&#xfc;r Member-Funktionen wird aufgegeben">
<arrowlink COLOR="#c12834" DESTINATION="ID_122504390" ENDARROW="Default" ENDINCLINATION="-5;64;" ID="Arrow_ID_234610428" STARTARROW="None" STARTINCLINATION="-330;-9;"/>
<font ITALIC="true" NAME="SansSerif" SIZE="14"/>
<icon BUILTIN="yes"/>
</node>
</node>
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1697327466147" ID="ID_893621038" MODIFIED="1697327486730" TEXT="dann wohl doch besser ganz unten die Spezalbehandlung f&#xfc;r bool-Flags?">
<icon BUILTIN="help"/>
<node CREATED="1697327490408" ID="ID_608568247" MODIFIED="1697327514952" TEXT="zumindest ist die Policy ein besserer Ort f&#xfc;r solche technischen Spezialit&#xe4;ten"/>
<node CREATED="1697327515500" ID="ID_1897397765" MODIFIED="1697327536325" TEXT="andererseits ist es dann &#xfc;berhaupt nicht mehr offensichtlich, da&#xdf; hier Magie passiert"/>
<node BACKGROUND_COLOR="#ccb59b" COLOR="#6e2a38" CREATED="1697327536914" ID="ID_623387180" MODIFIED="1697327566298" TEXT="STOP! was soll der Schei&#xdf;??">
<font ITALIC="true" NAME="SansSerif" SIZE="14"/>
<icon BUILTIN="stop-sign"/>
<icon BUILTIN="yes"/>
<node CREATED="1697327583331" ID="ID_31944681" MODIFIED="1697327614419" TEXT="so viel Aufwand f&#xfc;r so was Abstruses...."/>
<node CREATED="1697327570448" ID="ID_1381500606" MODIFIED="1697327582072" TEXT="&#x3bb; und gut is!!!!">
<icon BUILTIN="ksmiletris"/>
</node>
<node CREATED="1697327624318" ID="ID_532856293" MODIFIED="1697327699095" TEXT="is besser so">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
&#955;-Notation ist inzwischen allgemein bekannt, und hat den Vorteil, da&#223; das Binding nahe am verwendeten Code liegt. Das gilt ganz besonders auch f&#252;r bool-Flags, und zudem m&#252;ssen wir uns dann nicht mehr mit Konvertierungen, volatile und Atomics herumschlagen
</p>
</body>
</html>
</richcontent>
<icon BUILTIN="idea"/>
</node>
</node>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1697320502329" ID="ID_195583180" MODIFIED="1697329841076" TEXT="Umbau">
<icon BUILTIN="pencil"/>
<node COLOR="#435e98" CREATED="1697320475144" ID="ID_1616210437" MODIFIED="1697329834862" TEXT="Anpassungen nur bis in den Lock-Guard treiben">
<icon BUILTIN="full-1"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1697320520036" ID="ID_304531035" MODIFIED="1697320544119" TEXT="Lock-Guard-API umbauen">
<icon BUILTIN="full-2"/>
</node>
</node>
</node>
<node CREATED="1697317281147" ID="ID_1588035403" MODIFIED="1697317292949" TEXT="API-Anpassungen Codebasis">
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1697320909394" ID="ID_1421524615" MODIFIED="1697320924162" TEXT="Darstellung der Condition">
<icon BUILTIN="flag-yellow"/>
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1697321092943" ID="ID_719498386" MODIFIED="1697321100123" TEXT="Tickets">
<icon BUILTIN="info"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1697320925209" ID="ID_709630203" MODIFIED="1697321091019" TEXT="#1057 conditional wait (monitor) const correctness">
<icon BUILTIN="flag-yellow"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1697321013532" ID="ID_1169031361" MODIFIED="1697321091020" TEXT="#1051 allow lambdas for conditional wait (object monitor)">
<icon BUILTIN="flag-yellow"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1697321077876" ID="ID_1989704229" MODIFIED="1697321091020" TEXT="#994 integrate lambdas into function signature helpers">
<icon BUILTIN="flag-yellow"/>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1697321125783" ID="ID_1918158334" MODIFIED="1697321155131" TEXT="erst mal nur das API im Lock-Guard damit reproduzieren">
<icon BUILTIN="flag-yellow"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1697321155723" ID="ID_1441525836" MODIFIED="1697321170393" TEXT="dann alle Verwendungen auf Modernisierungs-Potential pr&#xfc;fen">
<icon BUILTIN="flag-yellow"/>
<node CREATED="1697326991042" ID="ID_163598257" MODIFIED="1697327008100" TEXT="alle Member-Pr&#xe4;dikate durch &#x3bb; ersetzen"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1697321173920" ID="ID_599504048" MODIFIED="1697321323733" TEXT="Tickets dokumentieren und schlie&#xdf;en">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
Im Besonderen #994 kann <i>nun wirklich langsam zugemacht werden! </i>Das schiebe ich nun schon so lange &#190; fertig vor mir her ... und es ist klar da&#223; ich den letzten Schritt (TYPES&lt;TY....&gt;) noch l&#228;nger vor mir her schiebe, wiewohl das eigentliche Problem effetiv bereits seit 2017 gel&#246;st ist
</p>
</body>
</html>
</richcontent>
<icon BUILTIN="flag-yellow"/>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1697317300096" ID="ID_169404073" MODIFIED="1697317304360" TEXT="direct-wait">
<icon BUILTIN="flag-yellow"/>
<node CREATED="1697317305951" ID="ID_59576653" MODIFIED="1697317610834">
<richcontent TYPE="NODE"><html>
<head>
</head>
<body>
<p>
hier hatte ich einen &#187;convenience-shortcut&#171; &#8212; und der <b><font color="#ae1010">ist broken</font></b>
</p>
</body>
</html>
</richcontent>
<arrowlink COLOR="#cb5590" DESTINATION="ID_276811059" ENDARROW="Default" ENDINCLINATION="-1328;-99;" ID="Arrow_ID_707193075" STARTARROW="None" STARTINCLINATION="-1717;72;"/>
<icon BUILTIN="messagebox_warning"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1697317397853" ID="ID_1226608020" MODIFIED="1697317440595" TEXT="Ersatz: anonyme-Instanz">
<icon BUILTIN="flag-yellow"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1697317413302" ID="ID_973377416" MODIFIED="1697317439510" TEXT="setzt besseren Support f&#xfc;r Member-Fun vorraus">
<icon BUILTIN="flag-yellow"/>
<node CREATED="1697323263283" ID="ID_420557101" MODIFIED="1697327252114" TEXT="geht nur bedingt">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
hab dummerweise den this-Ptr nicht mehr an dem Punkt; und das will ich auch nicht &#228;ndern &#8212; sonst hab ich in jeder dieser delegierenden Funktionen das getMonitor(this), und es ist auch inhaltlich nicht besonders pr&#228;zise, schlie&#223;lich arbeitet der Guard auf dem Monitor (siehe ClassLock)
</p>
</body>
</html>
</richcontent>
<linktarget COLOR="#9f5f73" DESTINATION="ID_420557101" ENDARROW="None" ENDINCLINATION="231;-36;" ID="Arrow_ID_1797357140" SOURCE="ID_28762827" STARTARROW="Default" STARTINCLINATION="-262;11;"/>
<linktarget COLOR="#b16c50" DESTINATION="ID_420557101" ENDARROW="Default" ENDINCLINATION="667;0;" ID="Arrow_ID_1731288409" SOURCE="ID_1950494758" STARTARROW="None" STARTINCLINATION="172;9;"/>
<icon BUILTIN="stop-sign"/>
</node>
<node COLOR="#5b280f" CREATED="1697323594831" ID="ID_779865512" MODIFIED="1697324219364" TEXT="ich k&#xf6;nnte was GRAUSAMES tun....">
<icon BUILTIN="help"/>
<icon BUILTIN="button_cancel"/>
<node CREATED="1697323619881" ID="ID_1097132135" MODIFIED="1697323650468" TEXT="reinterpret_cast&lt;Sync&amp;&gt; (montitor_)">
<icon BUILTIN="smiley-oh"/>
</node>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1697323756673" ID="ID_1871015044" MODIFIED="1697324176249" TEXT="das w&#xe4;re sogar einigerma&#xdf;en sicher">
<richcontent TYPE="NOTE">&lt;html&gt;
&lt;head&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;p&gt;
...und zwar wegen der Typedef &amp;quot;Monitor&amp;quot;, die nur im Scope von Sync&amp;lt;CONF&amp;gt;
definiert ist &amp;#8212; das geht gut, SOLANGE niemand das Layout der Klasse Sync
&amp;#228;ndert, niemand &amp;#8222;aus Versehen&amp;#8220; eine VTable einf&amp;#252;hrt, und solange niemand
den Typ Monitor abgreift, woanders instantiiert und dann diese Referenz
&amp;#252;ber eine von Lock abgeleitete Klasse in die Referenz einspielt. &lt;b&gt;&lt;font color=&quot;#ea1b82&quot;&gt;TJA&lt;/font&gt;&lt;/b&gt;&amp;#160;
&amp;#9785; diesen &amp;#8222;Jemand&amp;#8220; gibt es bereits: SyncClasslock &lt;font color=&quot;#ad0000&quot;&gt;&amp;#55357;&amp;#56817;&lt;/font&gt;
&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;
</richcontent>
<icon BUILTIN="closed"/>
</node>
<node CREATED="1697324181717" ID="ID_1476992683" MODIFIED="1697324227340" TEXT="Fazit: anst&#xe4;ndige Leute und so &#x2014; und au&#xdf;erdem w&#xe4;re es gef&#xe4;hrlich">
<icon BUILTIN="yes"/>
</node>
</node>
<node CREATED="1697323476231" ID="ID_1501185422" MODIFIED="1697324272133" TEXT="immerhin: Lambdas verringern den Schmerz">
<icon BUILTIN="idea"/>
</node>
</node>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1697318786633" ID="ID_336024786" MODIFIED="1697318873967" TEXT="ist aber u.U irref&#xfc;hrend">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
und zwar, weil eine solche anonyme Instanz den umschlie&#223;enden Scope nicht sch&#252;tzt; sie sieht aber syntaktisch genauso aus wie ein wirksamer Scope-Guard
</p>
</body>
</html>
</richcontent>
<icon BUILTIN="stop-sign"/>
</node>
</node>
<node COLOR="#338800" CREATED="1697318875030" ID="ID_1198984970" MODIFIED="1697329903095" TEXT="2.Alternative: den convenience-shortcut intern reparieren">
<icon BUILTIN="button_ok"/>
<node COLOR="#338800" CREATED="1697319005754" ID="ID_62443704" MODIFIED="1697329904503" TEXT="die interne delegation an die wait-Funktion per try-catch sch&#xfc;tzen">
<icon BUILTIN="button_ok"/>
</node>
<node COLOR="#338800" CREATED="1697319026138" ID="ID_383274889" MODIFIED="1697329905701" TEXT="im Fehlerfall explizit das Lock l&#xf6;sen">
<icon BUILTIN="button_ok"/>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1697319081650" ID="ID_1686143008" MODIFIED="1697319089823" TEXT="alle Verwendungen explizit durchpr&#xfc;fen">
<icon BUILTIN="flag-yellow"/>
</node>
</node>
<node CREATED="1697317628925" ID="ID_620668033" MODIFIED="1697321848776" TEXT="wait-timeout">
<linktarget COLOR="#6879a1" DESTINATION="ID_620668033" ENDARROW="Default" ENDINCLINATION="8;-31;" ID="Arrow_ID_542802268" SOURCE="ID_1779444313" STARTARROW="None" STARTINCLINATION="-148;7;"/>
<node CREATED="1697317643443" ID="ID_1921626506" MODIFIED="1697317648474" TEXT="Subsystem-Runner"/>
<node CREATED="1697317651618" ID="ID_694175448" MODIFIED="1697317655678" TEXT="Steam-Dispatcher"/>
</node>
<node CREATED="1697318178258" ID="ID_1033097807" MODIFIED="1697318198652" TEXT="notify_one|all">
<node CREATED="1697319530923" ID="ID_914687428" MODIFIED="1697319578775" TEXT="sollte ohne Lock aufrufbar sein">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
...rein konzeptionell ist es n&#228;mlich nicht notwendig, das Lock zu erlangen; aber unser bisheriges API hat dazu gezwungen. Nicht schlimm, aber auch nicht sch&#246;n
</p>
</body>
</html>
</richcontent>
</node>
<node CREATED="1697319626249" ID="ID_1229703089" MODIFIED="1697319643061" TEXT="static Sync::getMonitor(this) kann man verwenden">
<node CREATED="1697319680566" ID="ID_875413808" MODIFIED="1697319698527" TEXT="das &quot;this&quot; ist hier eine ungl&#xfc;ckliche Konsequenz des Monitor-Patterns"/>
<node CREATED="1697319733263" ID="ID_1982854355" MODIFIED="1697319793219" TEXT="...denn es geht um andere Threads, nicht um die Instanz"/>
</node>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#d2beaf" COLOR="#5c4d6e" CREATED="1697238399214" ID="ID_38924085" MODIFIED="1697238402259" TEXT="Stufe-3">
<icon BUILTIN="hourglass"/>
@ -66865,9 +67212,7 @@
<icon BUILTIN="hourglass"/>
<node CREATED="1697229756390" ID="ID_1054796650" MODIFIED="1697230627356" TEXT="erster Wurf seit vielen Jahren im Einsatz">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
...hatte ich damals sehr schnell geschrieben, um zu zeigen da&#223; eine C++ - L&#246;sung auch &#187;einfach&#171; sein kann. Chistian wollte damals unbedingt die Application-main in C implementieren, &#8222;damit alles wirklich einfach und verst&#228;ndlich bleibt&#8220;. Ich hatte das Gef&#252;hl, da stand eine Agenda im Raum, da&#223; alles Wichtige in C sein sollte. Ich vertrat (und vertrete bis heute) den Standpunkt, da&#223; die Erweiterungen in C++ aus gutem Grunde geschaffen wurden, weil C in wesentlichen Aspekten mutwillig zu einfach gehalten ist. F&#252;r den Traum von der <i>sch&#246;nen einfachen L&#246;sung</i>&#160;zahlt man dann jeden Tag Zinsen f&#252;r technische Schulden.
@ -66880,9 +67225,7 @@
<icon BUILTIN="broken-line"/>
<node CREATED="1697230653730" ID="ID_777823460" MODIFIED="1697230691378">
<richcontent TYPE="NODE"><html>
<head>
</head>
<head/>
<body>
<p>
sie erf&#252;llt alle Anforderungen, ist aber <i>zu sehr vereinfacht</i>
@ -66893,9 +67236,7 @@
<node CREATED="1697230694524" ID="ID_939615565" MODIFIED="1697230717045" TEXT="der Subsystem-Lebenszyklus setzt zu stark auf Konventionen"/>
<node CREATED="1697230726208" ID="ID_1811646071" MODIFIED="1697231115768" TEXT="es fehlen &#xdc;bergangs-Zust&#xe4;nde, die in der Realit&#xe4;t eben auftreten">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
Vor allem...
@ -66928,9 +67269,7 @@
</node>
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1697231867607" ID="ID_894790570" MODIFIED="1697232116770" TEXT="durch einen Trick im Object-Monitor implementiert">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
In lib::Sync (genauer: in der Implementierung Monitor-wait) war eine Unterst&#252;tzung f&#252;r Timeout nach POSIX eingebaut worden. Dies erfordert, da&#223; die Timeout-Spec in der Storage des Client bereitgehalten wird (weil man POSIX-Funktionen nur einen Pointer &#252;bergibt). Das habe ich hierf&#252;r ausgen&#252;tzt, indem nachtr&#228;glich, im Fall einer Emergency, noch ein Timeout definiert wird. Da Condition-Variablen zur Pr&#252;fung der Bedingung immer wieder aufgeweckt werden, kann man so nachtr&#228;glich eine Art vorzeitigen Abbruch realisieren...
@ -83322,6 +83661,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1696120192842" ID="ID_276811059" MODIFIED="1696120264827" TEXT="Bug im wait-&#xbb;convenience-shorcut&#xab;">
<linktarget COLOR="#682b39" DESTINATION="ID_276811059" ENDARROW="Default" ENDINCLINATION="617;-40;" ID="Arrow_ID_599709584" SOURCE="ID_323663607" STARTARROW="None" STARTINCLINATION="-274;12;"/>
<linktarget COLOR="#cb5590" DESTINATION="ID_276811059" ENDARROW="Default" ENDINCLINATION="-1328;-99;" ID="Arrow_ID_707193075" SOURCE="ID_59576653" STARTARROW="None" STARTINCLINATION="-1717;72;"/>
<icon BUILTIN="broken-line"/>
<node CREATED="1696120269872" ID="ID_538013070" MODIFIED="1696120281507" TEXT="denkbar w&#xe4;re stattdessen eine statische Methode"/>
<node CREATED="1696120282704" ID="ID_1767472760" MODIFIED="1696120305079" TEXT="(oder man verzichtet komplett auf den &#x201e;shortcut&#x201c;)"/>
@ -96446,7 +96786,7 @@ class Something
</node>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1696859902445" ID="ID_428140801" MODIFIED="1696859968378" TEXT="Beobachtungen...">
<icon BUILTIN="help"/>
<node CREATED="1696859972822" FOLDED="true" ID="ID_1229021778" MODIFIED="1696860322728" TEXT="sporadisch gescheiterte Tests">
<node CREATED="1696859972822" FOLDED="true" ID="ID_1229021778" MODIFIED="1697299049366" TEXT="sporadisch gescheiterte Tests">
<icon BUILTIN="messagebox_warning"/>
<node CREATED="1696859985804" ID="ID_798414043" MODIFIED="1696860302374" TEXT="23-10-09: JobPlanning_test">
<richcontent TYPE="NOTE"><html>
@ -96493,6 +96833,40 @@ class Something
</body>
</html></richcontent>
</node>
<node COLOR="#5b280f" CREATED="1697243084759" FOLDED="true" ID="ID_1455547060" MODIFIED="1697299048521" TEXT="23-10-14: DiagnosticContext_test // ThreadJoinable">
<richcontent TYPE="NOTE"><html>
<head/>
<body>
<p>
Zuf&#228;llig aber durchaus regelm&#228;&#223;ig wieder auftretendes Fehlverhalten
</p>
<ul>
<li>
der Test erzeugt 75 ThreadJoinable, welche jeweils eine rekursive Berechnung mit thread_lokal storage und sleep machen
</li>
<li>
danach explizit alle Threads join()
</li>
<li>
&#10233; aus den aufgesammelten lib::Result wird manchmal die Platzhalter-Exception ausgeworfen, mit der in der Policy zu Beginn der std::exception_ptr vorbelegt wurde (&quot;No result yet, thread still running; need to join() first.&quot;).
</li>
</ul>
<p>
<u>Theoretische Analyse</u>: in der Doku (Cppreference) hei&#223;t es, join() synchornizes-with dem Ende des Thread. Eigentlich w&#252;rde ich daraus schlu&#223;folgern, da&#223; wir auch eine release-acquire-Barriere haben. Das k&#246;nnte aber <b>eine zu starke Schlu&#223;folgerung</b>&#160;sein. Wir erzeugen ja im Thread ein neues lib::Result und weisen das per move-assign zu; wenn der Effekt der Zuweisung auf den eingebetteten std::exception_ptr im Haupt-Thread noch nicht sichtbar ist, w&#252;rde das beobachtete Verhalten resultieren.
</p>
<p>
Aber ich sehe auch noch eine <b>zweite Theorie</b>: gestern hatte ich an den Anfang der ThreadLifecycle::invokeThreadFunction() einen Guard eingef&#252;gt, zum Schutz gegen eine Exception aus dem Konstruktor einer abgeleiteten Klasse; d.h. wenn es den Wrapper gar nicht(mehr) gibt, soll die Thread-Funktion ebenfalls ganz ger&#228;uschlos verschwinden. K&#246;nnte es sein, da&#223; die Bedingung Policy::isLive() zu Beginn des Thread nicht zuverl&#228;ssig anspricht? Falls das passiert, w&#252;rde dann auch das eingebettete lib::Result nicht zugewiesen, der Thread w&#228;re aber im Mater-Thread sp&#228;ter als Joinable markiert, und das beobachtete Verhalten w&#228;re die Folge.
</p>
</body>
</html></richcontent>
<icon BUILTIN="button_cancel"/>
<node COLOR="#435e98" CREATED="1697298338695" ID="ID_141412141" MODIFIED="1697299041831" TEXT="aufgekl&#xe4;rt: der Guard am Anfang der Thread-Funktion verursacht das...">
<icon BUILTIN="idea"/>
</node>
<node CREATED="1697299012571" ID="ID_1800026408" MODIFIED="1697299046813" TEXT="es ist also die 2.Theorie (das ist zwar auch beunruhigend, aber weniger als die 1.Theorie)">
<icon BUILTIN="smiley-neutral"/>
</node>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#d2beaf" COLOR="#5c4d6e" CREATED="1689610305547" ID="ID_1569437785" MODIFIED="1689610311743" TEXT="QA-testing">