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:
parent
c37871ca78
commit
73737f2aee
7 changed files with 536 additions and 152 deletions
|
|
@ -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()}
|
||||
{ }
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
134
src/lib/sync.hpp
134
src/lib/sync.hpp
|
|
@ -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_; }
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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ß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üßte man diesen Fall auf einen »Autonomous Thread« einschrä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 — und führt in anderen Fällen zu Fehlverhalten">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
Da bin ich einem Kurzschluß 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> in anderen Konstellationen führt: es kommt sporadisch vor, daß isLive() zu Beginn des Threads noch nicht wahr liefert; die Gründe ließen sich nicht aufklären. In einem solchen Fall würde der Thread spurlos terminieren — und dadurch an anderer Stelle mö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ß dann als eigenes unique_lock-Token repräsentiert werden.
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
<node CREATED="1697211431074" ID="ID_921453654" MODIFIED="1697211474012" TEXT="⟹ 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> 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ü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ß man ein grade gesperrtes Mutex einfach „fahren läßt“ — 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äsives Stück Code mit einem schmalen API nach auß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 ⟹ 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ür C++ zu ü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ür „wilden“ Direkt-Gebrauch">
|
||||
<node CREATED="1697156532544" ID="ID_273574678" MODIFIED="1697156637966" TEXT="denn ursprü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ß 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ß ich überhaupt nichts anderes brauche, als nur das Lock-Guard front-End (+Atomics für alle nicht-trivialen Fälle).
|
||||
|
|
@ -66587,9 +66584,7 @@
|
|||
<node CREATED="1697156976195" ID="ID_681854744" MODIFIED="1697156985008" TEXT="deshalb kann auch alles Andere zurückgebaut werden"/>
|
||||
<node CREATED="1697157070044" ID="ID_1501146985" MODIFIED="1697157223059" TEXT="die unique_lock-Instanz ist zugleich Verbesserung und zusä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ätzlicher Storage-Ballast, der eigentlich nicht notwendig wä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 »strukturellen Verbesserung« direkt zu implementieren, aber in dieser Hinsicht überschätze ich häufig die reale Komplexitä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ö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ü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ä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älle als separate Methode herauszufü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ä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ä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ückgeführt"/>
|
||||
</node>
|
||||
<node CREATED="1697318499319" ID="ID_1385588809" MODIFIED="1697318512954" TEXT="Member-Funktion des Monitor-Trä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ügt, die Referenz per Signatur zu erzwingen">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
Hier gibt es zwar eine Lücke, nämlich die const& auf einen rvalue — 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ß 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 ü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ß nicht speziell auf den Typ des Trä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ä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 überhaupt sinnvoll, Member-Prädikate speziell zu unterstü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önnen sie nur in einem Spezial-Konstruktor direkt unterstü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ätte dann also zwei verschiedene APIs fü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ö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, &MyClass::predicate}"/>
|
||||
<node CREATED="1697326825569" ID="ID_1892485138" MODIFIED="1697326884997" TEXT="Lock sync{this, [&]{ return predicate(); }}"/>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#ccb59b" COLOR="#6e2a38" CREATED="1697326947256" ID="ID_1582251486" MODIFIED="1697327107741" TEXT="Beschluß: Support fü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ür bool-Flags?">
|
||||
<icon BUILTIN="help"/>
|
||||
<node CREATED="1697327490408" ID="ID_608568247" MODIFIED="1697327514952" TEXT="zumindest ist die Policy ein besserer Ort für solche technischen Spezialitäten"/>
|
||||
<node CREATED="1697327515500" ID="ID_1897397765" MODIFIED="1697327536325" TEXT="andererseits ist es dann überhaupt nicht mehr offensichtlich, daß hier Magie passiert"/>
|
||||
<node BACKGROUND_COLOR="#ccb59b" COLOR="#6e2a38" CREATED="1697327536914" ID="ID_623387180" MODIFIED="1697327566298" TEXT="STOP! was soll der Scheiß??">
|
||||
<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ür so was Abstruses...."/>
|
||||
<node CREATED="1697327570448" ID="ID_1381500606" MODIFIED="1697327582072" TEXT="λ 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>
|
||||
λ-Notation ist inzwischen allgemein bekannt, und hat den Vorteil, daß das Binding nahe am verwendeten Code liegt. Das gilt ganz besonders auch für bool-Flags, und zudem mü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üfen">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node CREATED="1697326991042" ID="ID_163598257" MODIFIED="1697327008100" TEXT="alle Member-Prädikate durch λ ersetzen"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1697321173920" ID="ID_599504048" MODIFIED="1697321323733" TEXT="Tickets dokumentieren und schließ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 ¾ fertig vor mir her ... und es ist klar daß ich den letzten Schritt (TYPES<TY....>) noch länger vor mir her schiebe, wiewohl das eigentliche Problem effetiv bereits seit 2017 gelö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 »convenience-shortcut« — 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ü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 ändern — sonst hab ich in jeder dieser delegierenden Funktionen das getMonitor(this), und es ist auch inhaltlich nicht besonders präzise, schließ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önnte was GRAUSAMES tun....">
|
||||
<icon BUILTIN="help"/>
|
||||
<icon BUILTIN="button_cancel"/>
|
||||
<node CREATED="1697323619881" ID="ID_1097132135" MODIFIED="1697323650468" TEXT="reinterpret_cast<Sync&> (montitor_)">
|
||||
<icon BUILTIN="smiley-oh"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1697323756673" ID="ID_1871015044" MODIFIED="1697324176249" TEXT="das wäre sogar einigermaßen sicher">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
...und zwar wegen der Typedef &quot;Monitor&quot;, die nur im Scope von Sync&lt;CONF&gt;
|
||||
definiert ist &#8212; das geht gut, SOLANGE niemand das Layout der Klasse Sync
|
||||
&#228;ndert, niemand &#8222;aus Versehen&#8220; eine VTable einf&#252;hrt, und solange niemand
|
||||
den Typ Monitor abgreift, woanders instantiiert und dann diese Referenz
|
||||
&#252;ber eine von Lock abgeleitete Klasse in die Referenz einspielt. <b><font color="#ea1b82">TJA</font></b>&#160;
|
||||
&#9785; diesen &#8222;Jemand&#8220; gibt es bereits: SyncClasslock <font color="#ad0000">&#55357;&#56817;</font>
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
<icon BUILTIN="closed"/>
|
||||
</node>
|
||||
<node CREATED="1697324181717" ID="ID_1476992683" MODIFIED="1697324227340" TEXT="Fazit: anständige Leute und so — und außerdem wäre es gefä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ührend">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
und zwar, weil eine solche anonyme Instanz den umschließenden Scope nicht schü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ützen">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1697319026138" ID="ID_383274889" MODIFIED="1697329905701" TEXT="im Fehlerfall explizit das Lock lö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ü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ämlich nicht notwendig, das Lock zu erlangen; aber unser bisheriges API hat dazu gezwungen. Nicht schlimm, aber auch nicht schö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 "this" ist hier eine unglü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ß eine C++ - Lösung auch »einfach« sein kann. Chistian wollte damals unbedingt die Application-main in C implementieren, „damit alles wirklich einfach und verständlich bleibt“. Ich hatte das Gefühl, da stand eine Agenda im Raum, daß alles Wichtige in C sein sollte. Ich vertrat (und vertrete bis heute) den Standpunkt, daß die Erweiterungen in C++ aus gutem Grunde geschaffen wurden, weil C in wesentlichen Aspekten mutwillig zu einfach gehalten ist. Für den Traum von der <i>schönen einfachen Lösung</i> zahlt man dann jeden Tag Zinsen fü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ü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 Übergangs-Zustände, die in der Realitä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ützung für Timeout nach POSIX eingebaut worden. Dies erfordert, daß die Timeout-Spec in der Storage des Client bereitgehalten wird (weil man POSIX-Funktionen nur einen Pointer übergibt). Das habe ich hierfür ausgenützt, indem nachträglich, im Fall einer Emergency, noch ein Timeout definiert wird. Da Condition-Variablen zur Prüfung der Bedingung immer wieder aufgeweckt werden, kann man so nachträglich eine Art vorzeitigen Abbruch realisieren...
|
||||
|
|
@ -83322,6 +83661,7 @@ Date:   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-»convenience-shorcut«">
|
||||
<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äre stattdessen eine statische Methode"/>
|
||||
<node CREATED="1696120282704" ID="ID_1767472760" MODIFIED="1696120305079" TEXT="(oder man verzichtet komplett auf den „shortcut“)"/>
|
||||
|
|
@ -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ällig aber durchaus regelmäß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>
|
||||
⟹ aus den aufgesammelten lib::Result wird manchmal die Platzhalter-Exception ausgeworfen, mit der in der Policy zu Beginn der std::exception_ptr vorbelegt wurde ("No result yet, thread still running; need to join() first.").
|
||||
</li>
|
||||
</ul>
|
||||
<p>
|
||||
<u>Theoretische Analyse</u>: in der Doku (Cppreference) heißt es, join() synchornizes-with dem Ende des Thread. Eigentlich würde ich daraus schlußfolgern, daß wir auch eine release-acquire-Barriere haben. Das könnte aber <b>eine zu starke Schlußfolgerung</b> 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ü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ü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äuschlos verschwinden. Könnte es sein, daß die Bedingung Policy::isLive() zu Beginn des Thread nicht zuverlässig anspricht? Falls das passiert, würde dann auch das eingebettete lib::Result nicht zugewiesen, der Thread wäre aber im Mater-Thread später als Joinable markiert, und das beobachtete Verhalten wäre die Folge.
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
<icon BUILTIN="button_cancel"/>
|
||||
<node COLOR="#435e98" CREATED="1697298338695" ID="ID_141412141" MODIFIED="1697299041831" TEXT="aufgeklä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">
|
||||
|
|
|
|||
Loading…
Reference in a new issue