Library: draft a SyncBarrier latch
Intended as replacement for the Mutex/ConditionVar based barrier built into the exiting Lumiera thread handling framework and used to ensure safe hand-over of a bound functor into the starting new thread. The standard requires a comparable guarantee for the C++17 concurrency framework, expressed as a "synchronizes_with" assertion along the lines of the Atomics framework. While in most cases dedicated synchronisation is thus not required anymore when swtiching to C++17, some special extended use cases remain to be addressed, where the complete initialisation of further support framework must be ensured. With C++20 this would be easy to achieve with a std::latch, so we need a simple workaround for the time being. After consideration of the typical use case, I am aiming at a middle ground in terms of performance, by using a yield-wait until satisfying the latch condition.
This commit is contained in:
parent
416895b5b2
commit
6735857f3b
6 changed files with 397 additions and 28 deletions
|
|
@ -61,6 +61,7 @@
|
|||
** - in a similar vein, the *filter operation* binds a predicate to decide about using or discarding data
|
||||
** - in concert, expand- and transform operation allow to build hierarchy evaluation algorithms without exposing
|
||||
** any knowledge regarding the concrete hierarchy used and explored as data source.
|
||||
** - further special convenience adaptors and _terminal functions_ are provided.
|
||||
**
|
||||
** In itself, the IterExplorer is an iterator with implementation defined type (all operations being inlined).
|
||||
** But it is possible to package this structure behind a conventional iteration interface with virtual functions.
|
||||
|
|
@ -1586,6 +1587,20 @@ namespace lib {
|
|||
return SRC {move(*this)};
|
||||
}
|
||||
|
||||
/**
|
||||
* _terminal builder_ to invoke a functor for side effect on the complete pipeline.
|
||||
* @note exhausts and discards the pipeline itself
|
||||
*/
|
||||
template<class FUN>
|
||||
void
|
||||
foreach (FUN&& consumer)
|
||||
{
|
||||
auto consumeFun = iter_explorer::_FunTraits<FUN,SRC>::adaptFunctor (forward<FUN> (consumer));
|
||||
SRC& pipeline = *this;
|
||||
for ( ; pipeline; ++pipeline)
|
||||
consumeFun (pipeline);
|
||||
}
|
||||
|
||||
/** _terminal builder_ to pour and materialise all results from this Pipeline.
|
||||
* @tparam CON a STL compliant container to store generated values (defaults to `vector`)
|
||||
* @return new instance of the target container, filled with all values
|
||||
|
|
|
|||
85
src/lib/sync-barrier.hpp
Normal file
85
src/lib/sync-barrier.hpp
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
SYNC-BARRIER.hpp - N-fold synchronisation point with yield-wait
|
||||
|
||||
Copyright (C) Lumiera.org
|
||||
2023, Hermann Vosseler <Ichthyostega@web.de>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
/** @file sync-barrier.hpp
|
||||
** A N-fold synchronisation latch using yield-wait until fulfilment.
|
||||
** Semantically, this barrier is similar to std::latch (introduced with C++20).
|
||||
** It is intended for one-time use and blocks any invocation until N invocations occurred.
|
||||
** The »wait« however is implemented as a spinning loop with `std::this_thread::yield`,
|
||||
** which places this implementation into a middle ground between a full-fledged blocking
|
||||
** lock and a busy spinning log. The `yield()` call is expected to de-prioritise the current
|
||||
** thread behind all other threads currently amenable for active execution, without actually
|
||||
** placing the thread into sleeping state. The coordination of the latch relies on Atomics.
|
||||
** @see SyncBarrier_test
|
||||
** @see steam::control::DispatcherLoop
|
||||
** @todo as of 9/2023 it remains to be seen if this facility is just a pre-C++20 workaround;
|
||||
** otherwise it may present distinct performance characteristics than std::latch,
|
||||
** possibly also a slightly more abstracted (and thus clearer) usage API.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef LIB_SYNC_BARRIER_H
|
||||
#define LIB_SYNC_BARRIER_H
|
||||
|
||||
|
||||
#include "lib/error.hpp"
|
||||
#include "lib/nocopy.hpp"
|
||||
//#include "include/logging.h"
|
||||
//#include "lib/meta/function.hpp"
|
||||
//#include "lib/result.hpp"
|
||||
|
||||
//#include <utility>
|
||||
#include <atomic>
|
||||
|
||||
|
||||
namespace lib {
|
||||
|
||||
// using lib::Literal;
|
||||
// namespace error = lumiera::error;
|
||||
// using error::LERR_(STATE);
|
||||
// using error::LERR_(EXTERNAL);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @todo write type comment
|
||||
*/
|
||||
class SyncBarrier
|
||||
: util::NonCopyable
|
||||
{
|
||||
public:
|
||||
explicit
|
||||
SyncBarrier (size_t nFold =2)
|
||||
{ }
|
||||
|
||||
void
|
||||
sync()
|
||||
{
|
||||
UNIMPLEMENTED ("count-down latch logic");
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
} // namespace lib
|
||||
#endif /*LIB_SYNC_BARRIER_H*/
|
||||
148
tests/library/sync-barrier-test.cpp
Normal file
148
tests/library/sync-barrier-test.cpp
Normal file
|
|
@ -0,0 +1,148 @@
|
|||
/*
|
||||
SyncBarrier(Test) - verify yield-waiting synchronisation latch
|
||||
|
||||
Copyright (C) Lumiera.org
|
||||
2023, Hermann Vosseler <Ichthyostega@web.de>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
* *****************************************************/
|
||||
|
||||
/** @file sync-barrier-test.cpp
|
||||
** unit test \ref SyncBarrier_test
|
||||
*/
|
||||
|
||||
|
||||
#include "lib/test/run.hpp"
|
||||
#include "lib/test/test-helper.hpp"
|
||||
|
||||
//#include "lib/thread.hpp"
|
||||
#include "lib/sync-barrier.hpp"
|
||||
#include "lib/iter-explorer.hpp"
|
||||
#include "lib/util-foreach.hpp"
|
||||
#include "lib/error.hpp"
|
||||
|
||||
//#include <utility>
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
#include <atomic>
|
||||
#include <array>
|
||||
|
||||
using test::Test;
|
||||
using util::and_all;
|
||||
using lib::explore;
|
||||
using std::atomic_uint;
|
||||
using std::array;
|
||||
|
||||
using std::this_thread::sleep_for;
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
|
||||
namespace lib {
|
||||
namespace test {
|
||||
|
||||
namespace {
|
||||
|
||||
const uint NUM_THREADS = 1024;
|
||||
|
||||
atomic_uint stage1{0};
|
||||
atomic_uint stage2{0};
|
||||
atomic_uint finish{0};
|
||||
|
||||
SyncBarrier interThread{NUM_THREADS};
|
||||
SyncBarrier afterThread{NUM_THREADS+1};
|
||||
|
||||
/**
|
||||
* A test thread to perform a summation protocol including synchronisation points
|
||||
* - build a compound sum of random numbers in the first stage
|
||||
* - wait for the compound sum to build up completely
|
||||
* - book in the compound sum plus a further random number
|
||||
*/
|
||||
class TestThread
|
||||
: std::thread ////////////////////////////////////////////////////////////////////OOO TOD-oh
|
||||
{
|
||||
public:
|
||||
TestThread()
|
||||
: thread{[&]()
|
||||
{ //-STAGE-1------------------------------
|
||||
localSum = rand() % 1000; // generate local value
|
||||
stage1.fetch_add (localSum); // book in local value
|
||||
interThread.sync(); // wait for all other threads to have booked in
|
||||
|
||||
//-STAGE-2------------------------------
|
||||
localSum += stage1; // pick up compounded sum from STAGE-1
|
||||
localSum += rand() % 1000; // add further local value for STAGE-2
|
||||
stage2.fetch_add (localSum); // book in local sum
|
||||
afterThread.sync(); // wait for other threads and supervisor
|
||||
|
||||
finish.fetch_add(1); // mark completion of this thread
|
||||
thread::detach(); //////////////////////////////////////////////OOO Wech-oh
|
||||
}}
|
||||
{ }
|
||||
|
||||
uint localSum; // *deliberately* not initialised to avoid race
|
||||
bool isRunning() const { return thread::joinable(); } ///////////////////////OOO Wack-oh
|
||||
};
|
||||
|
||||
|
||||
/** sum up all `localSum` fields from all TestThread instances in a container */
|
||||
template<class CON>
|
||||
uint
|
||||
sumLocals (CON const& threads)
|
||||
{
|
||||
uint sum{0};
|
||||
explore (threads)
|
||||
.foreach ([&](TestThread const& t){ sum += t.localSum; });
|
||||
return sum;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************//**
|
||||
* @test verify N-fold synchronisation points by multi-thread loat-test.
|
||||
*
|
||||
* @see lib::SyncBarrier
|
||||
* @see steam::control::DispatcherLoop
|
||||
*/
|
||||
class SyncBarrier_test : public Test
|
||||
{
|
||||
|
||||
virtual void
|
||||
run (Arg)
|
||||
{
|
||||
array<TestThread,NUM_THREADS> threads;
|
||||
|
||||
CHECK (0 == finish);
|
||||
CHECK (and_all (threads, [](auto& t){ return t.isRunning(); }));
|
||||
|
||||
afterThread.sync();
|
||||
sleep_for (1ms); // give the threads a chance to terminate
|
||||
|
||||
CHECK (NUM_THREADS == finish); // all threads have passed out....
|
||||
CHECK (0 < stage1);
|
||||
CHECK (stage1 < stage2);
|
||||
CHECK (stage2 > sumLocals(threads));
|
||||
CHECK (stage2 == sumLocals(threads) + NUM_THREADS*stage1); // this holds only if all threads waited to get the complete stage1 sum
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
/** Register this test class... */
|
||||
LAUNCHER (SyncBarrier_test, "function common");
|
||||
|
||||
|
||||
|
||||
}} // namespace lib::test
|
||||
|
|
@ -20,6 +20,10 @@
|
|||
|
||||
* *****************************************************/
|
||||
|
||||
/** @file thread-wrapper-self-recognition-test.cpp
|
||||
** unit test \ref ThreadWrapperSelfRecognitionTest_test
|
||||
*/
|
||||
|
||||
|
||||
#include "lib/test/run.hpp"
|
||||
#include "lib/test/test-helper.hpp"
|
||||
|
|
|
|||
|
|
@ -378,7 +378,7 @@ namespace test {
|
|||
CHECK (!and_all (coll, [] (uint elm) { return 1 < elm; }));
|
||||
|
||||
CHECK ( has_any (coll, [] (uint elm) { return 0 < elm; }));
|
||||
CHECK ( has_any (coll, [] (uint elm) { return elm >= NUM_ELMS; }));
|
||||
CHECK ( has_any (coll, [] (uint elm) { return elm == NUM_ELMS; }));
|
||||
CHECK (!has_any (coll, [] (uint elm) { return elm > NUM_ELMS; }));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -79616,6 +79616,13 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
<node CREATED="1695335516996" ID="ID_1023062994" MODIFIED="1695335550147" TEXT="der normale Thread würde sich dann stets am Ende selbst detachen"/>
|
||||
<node CREATED="1695335555337" ID="ID_712387888" MODIFIED="1695335682482" TEXT="damit fällt ein Anlaß für Flüchtigkeitsfehler weg"/>
|
||||
<node CREATED="1695335705339" ID="ID_164690747" MODIFIED="1695335719461" TEXT="paßt damit zusammen, daß wir auch einen try-catch-Block einbauen"/>
|
||||
<node CREATED="1695392987999" ID="ID_109089425" MODIFIED="1695393002077" TEXT="wird (derzeit und absehbar) nur für Tests verwendet">
|
||||
<icon BUILTIN="info"/>
|
||||
<node CREATED="1695393029161" ID="ID_1726147640" MODIFIED="1695393053763" TEXT="und dafür ist auch die Fehler-Weitergabe sinnvoll"/>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1695393054345" ID="ID_582803458" MODIFIED="1695393067033" TEXT="also auch dieses Zusatz-Feature erhalten">
|
||||
<icon BUILTIN="yes"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1695313818614" ID="ID_470584516" MODIFIED="1695313837839" TEXT="Thread::syncPoint() / sync()">
|
||||
<node CREATED="1695315415143" ID="ID_1102877346" MODIFIED="1695315425412" TEXT="bisherige Verwendungen">
|
||||
|
|
@ -79641,8 +79648,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
sonst könnte der Fall nicht zuverlässig getestet werden, daß der Test-Runner selber kurz nach dem Start stirbt
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1695315325887" ID="ID_625375733" MODIFIED="1695315328199" TEXT="SessionCommandFunction_test">
|
||||
|
|
@ -79663,42 +79669,73 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
<icon BUILTIN="idea"/>
|
||||
<node CREATED="1695334637793" ID="ID_681204225" MODIFIED="1695334721438" TEXT="spinning ohne yield wäre gefährlich im allgemeinen Fall">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
ein Spinlock sollte man nur verwenden, wenn man sicher sein kann, daß man (a) fast nicht warten muß und (b) die CPU für sich hat. Andernfalls kann das schlimmstenfalls zum Verhungern des ganzen Systems führen...
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
<node CREATED="1695334757953" ID="ID_1716551234" MODIFIED="1695334788969">
|
||||
<richcontent TYPE="NODE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
Mutex + ConditionVar ist auch <i>gar nicht so schlecht</i> <font size="2">(aber noch schwergewichtiger)</font>
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
<node CREATED="1695334869074" ID="ID_938671107" MODIFIED="1695335156463" TEXT="yield() gefällt mir — weil es typischerweise genau um einen Thread-Schedule-delay geht">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
Der Sprachstandard garantiert bereits, daß der Thread startklar ist, wenn der std::thread-Konstruktor verlassen wird. Allerdings kann es immer passieren, daß dummerweise der OS-Scheduler grade Anderes mit dieser CPU vor hat — und genau dann laufen wir in die Situation, vor der diese Sync-Barriere schützen soll; d.h. <i>spätestens nach einer Schedule-Runde</i> sollten alle Threads einmal vorbeigekommen sein.
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</html></richcontent>
|
||||
<arrowlink COLOR="#6493ca" DESTINATION="ID_1673241488" ENDARROW="Default" ENDINCLINATION="210;16;" ID="Arrow_ID_2380452" STARTARROW="None" STARTINCLINATION="10;28;"/>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1695391836532" ID="ID_373841600" MODIFIED="1695410342100" TEXT="lib::SyncBarrier implementieren">
|
||||
<icon BUILTIN="flag-pink"/>
|
||||
<node CREATED="1695391870343" ID="ID_500508570" MODIFIED="1695392284932" TEXT="bewußt nur zur Einmal-Verwendung">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
Wiederverwendung nach automatischem <i>Reset nach Erfüllung </i>ist in manchen Situationen verdammt tückisch; ohnehin stellt ein Latch stets eine Deadlock-Gefahr dar.
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
<node CREATED="1695391893285" ID="ID_33727698" MODIFIED="1695392105718" TEXT="könnte ein Vorgriff sein auf std::latch">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
...darauf läuft es nämlich hinaus; wenn wir tatsächlich auf C++20 sind, sollte die genaue API-Semantik und das Laufzeitverhalten bewertet werden, um zu entscheiden, ob beide Lösungen äquivalent sind...
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
<node CREATED="1695392297550" ID="ID_1673241488" MODIFIED="1695392410883" TEXT="Entscheidung: verwende yield-wait">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
Letztlich eine Entscheidung nach Bauchgefühl und ohne konkreten Anhaltspunkt; die Entscheidung kann erst überprüft werden, wenn es belastbare Einsatz-Szenarien gibt
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
<linktarget COLOR="#6493ca" DESTINATION="ID_1673241488" ENDARROW="Default" ENDINCLINATION="210;16;" ID="Arrow_ID_2380452" SOURCE="ID_938671107" STARTARROW="None" STARTINCLINATION="10;28;"/>
|
||||
<icon BUILTIN="yes"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1695392426479" ID="ID_281891239" MODIFIED="1695394808033" TEXT="Test per Load-Test">
|
||||
<arrowlink COLOR="#2b3fa9" DESTINATION="ID_1220273122" ENDARROW="Default" ENDINCLINATION="169;-7;" ID="Arrow_ID_1739726561" STARTARROW="None" STARTINCLINATION="15;204;"/>
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
|
|
@ -79715,16 +79752,13 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
<icon BUILTIN="flag-pink"/>
|
||||
<node CREATED="1695339498617" ID="ID_1329617125" MODIFIED="1695339543619" TEXT="umgezogene Tests gebrochen">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
solange sie noch auf den alten Code gehen, der den Threadpool voraussetzt (welcher aber für Library-Tests nicht zugelinkt wird)
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</html></richcontent>
|
||||
<node CREATED="1695339558729" ID="ID_1181374984" MODIFIED="1695339576171" TEXT="SyncLocking_test"/>
|
||||
<node CREATED="1695339549851" ID="ID_1030547189" MODIFIED="1695339553543" TEXT="SyncClasslock_test"/>
|
||||
<node CREATED="1695339568255" ID="ID_288867443" MODIFIED="1695339574891" TEXT="ThreadWrapper_test"/>
|
||||
|
|
@ -79748,16 +79782,13 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
<icon BUILTIN="yes"/>
|
||||
<node CREATED="1695336524821" ID="ID_625640883" MODIFIED="1695336587478" TEXT="Begründung: es ist kein »Vault-Feature« mehr">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
Denn wir betreiben hier nun keine System-Einrichtungen mehr, keinen Resource-Collector und keinen Threadpool. Es handelt sich lediglich um Adapter über der Std-Lib
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
<node CREATED="1695336588389" ID="ID_1245830716" MODIFIED="1695336597664" TEXT="außerdem erleichtert das den Schwenk"/>
|
||||
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1695340272418" ID="ID_1240703198" MODIFIED="1695340308005" TEXT="Code aus namespace vault zurückbauen">
|
||||
|
|
@ -79771,6 +79802,57 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1695394188133" ID="ID_1229328590" MODIFIED="1695394203632" TEXT="Umbau">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1695394205547" ID="ID_1719816317" MODIFIED="1695394259544" TEXT="Tests umstellen und modernisieren">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1695394270093" ID="ID_585437655" MODIFIED="1695394271819" TEXT="ThreadWrapper_test">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1695394288052" ID="ID_1407826381" MODIFIED="1695395666211" TEXT="Kritik: der testet nicht punktgenau">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
Dieser Test ist zwar <i>pfiffig</i> geschrieben, aber er testet eigentlich den Sync/Monitor, nicht den Thread-Wrapper. In der aktuellen Form ist er sogar nahe an der Thema-Verfehlung, weil überhaupt nicht getestet wird,  <i>daß mehrere Threads gestartet wurden und gelaufen sind</i>
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
<arrowlink COLOR="#fedec1" DESTINATION="ID_1532807851" ENDARROW="Default" ENDINCLINATION="416;-16;" ID="Arrow_ID_1646166026" STARTARROW="None" STARTINCLINATION="479;36;"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1695394418004" ID="ID_1846217863" MODIFIED="1695394504468" TEXT="testen: ein Aufruf pro Thread hat stattgefunden">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1695394519627" ID="ID_776125132" MODIFIED="1695394528873" TEXT="testen: individuelle Argumentübergabe">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1695394665822" ID="ID_881973960" MODIFIED="1695394668399" TEXT="ThreadWrapperJoin_test">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node CREATED="1695394703974" ID="ID_1918931115" MODIFIED="1695394714328" TEXT="erscheint bereits adäquat">
|
||||
<icon BUILTIN="yes"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1695394715296" ID="ID_1135505355" MODIFIED="1695394724096" TEXT="prüfen: ggfs Fehlercode durchgeben?">
|
||||
<icon BUILTIN="help"/>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1695394744028" ID="ID_1755648327" MODIFIED="1695394746744" TEXT="ThreadWrapperSelfRecognitionTest_test">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1695394753483" ID="ID_1338410455" MODIFIED="1695410354252" TEXT="SyncBarrier_test">
|
||||
<icon BUILTIN="flag-pink"/>
|
||||
<node CREATED="1695394763010" ID="ID_1220273122" MODIFIED="1695394801458" TEXT="neuer Test für neue (interims-) Implementierung">
|
||||
<linktarget COLOR="#2b3fa9" DESTINATION="ID_1220273122" ENDARROW="Default" ENDINCLINATION="169;-7;" ID="Arrow_ID_1739726561" SOURCE="ID_281891239" STARTARROW="None" STARTINCLINATION="15;204;"/>
|
||||
<icon BUILTIN="info"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1695394861413" ID="ID_1334580079" MODIFIED="1695394870676" TEXT="ggfs auch gleich Performance-Test vorbereiten">
|
||||
<icon BUILTIN="help"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1695394237210" ID="ID_11553358" MODIFIED="1695394251486" TEXT="Applikation umstellen">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1693789156806" ID="ID_128127845" MODIFIED="1693789195596" TEXT="Monitor erhalten und umschreiben">
|
||||
|
|
@ -79786,6 +79868,41 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
<node CREATED="1695337787989" ID="ID_154693007" MODIFIED="1695337808761" TEXT="ich errinnere mich, das nebenbei mit eingebaut zu haben..."/>
|
||||
<node CREATED="1695337809498" ID="ID_789251448" MODIFIED="1695337825212" TEXT="inzwischen gibt es da diverse bessere Möglichkeiten (mit Futures)"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1695395131329" ID="ID_1209350338" MODIFIED="1695395161594" TEXT="Umstellen der bestehenden Wrapper auf C++17">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1695395162340" ID="ID_188901559" MODIFIED="1695395168717" TEXT="Prüfen auf mögliche Vereinfachungen">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1695395186529" ID="ID_110802115" MODIFIED="1695395202288" TEXT="Tests überprüfen und modernisieren">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1695395205001" ID="ID_881035953" MODIFIED="1695395208312" TEXT="SyncLocking_test">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1695395218517" ID="ID_1241448952" MODIFIED="1695395351970" TEXT="Kritik: ist zwar fordernd, aber nicht klar">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
Der Test setzt das Locking zwar erheblich unter Druck, aber er ist so komplex, daß man sich einarbeiten muß, um ihn überhaupt zu verstehen
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1695395397765" ID="ID_1532807851" MODIFIED="1695395652825" TEXT="Idee: stattdessen den Checker aus ThreadWrapper_test verwenden">
|
||||
<linktarget COLOR="#fedec1" DESTINATION="ID_1532807851" ENDARROW="Default" ENDINCLINATION="416;-16;" ID="Arrow_ID_1646166026" SOURCE="ID_1407826381" STARTARROW="None" STARTINCLINATION="479;36;"/>
|
||||
<icon BUILTIN="idea"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1695395436073" ID="ID_735920726" MODIFIED="1695395466899" TEXT="wünschenswert: mit / ohne - Test">
|
||||
<icon BUILTIN="yes"/>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1695395469746" ID="ID_1750044155" MODIFIED="1695395500761" TEXT="den »ohne«-Test so auslegen, daß er (fast) immer scheitert">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1695395590676" ID="ID_1887210552" MODIFIED="1695395616570" TEXT="Wirksamkeit ist direkt im Test dokumentiert">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
|
|
|
|||
Loading…
Reference in a new issue