Library: change of plan - retain the »Either« wrapper

on second thought, the ability to transport an exception still seems
worthwhile, and can be achieved by some rearrangements in the design.

As preparation, reorganise the design of the Either-wrapper (lib::Result)
This commit is contained in:
Fischlurch 2023-09-27 01:27:53 +02:00
parent 59bb99f653
commit 4348e110cb
4 changed files with 416 additions and 93 deletions

View file

@ -52,74 +52,23 @@ namespace lib {
using util::isnil;
using std::string;
namespace error = lumiera::error;
/**
* Optional Result value or status of some operation.
* It can be created for passing a result produced by the operation, or the
* failure to do so. The value can be retrieved by implicit or explicit conversion.
* Representation of the result of some operation, _EITHER_ a value or a failure.
* It can be created for passing a result produced by the operation, or the failure
* to do so. The value can be retrieved by implicit or explicit conversion.
* @throw error::State on any attempt to access the value in case of failure
* @warning this class has a lot of implicit conversions;
* care should be taken when defining functions
* to take Result instances as parameter....
*/
template<typename RES>
class Result
{
string failureLog_;
wrapper::ItemWrapper<RES> value_;
public:
/** mark an invalid/failed result */
Result (string const& failureReason ="no result")
: failureLog_{failureReason}
{ }
/** failed result, with reason given.*/
Result (lumiera::Error const& reason)
: failureLog_{reason.what()}
{ }
/** standard case: valid result */
Result (RES&& value)
: failureLog_{}
, value_{std::forward<RES> (value)}
{ }
bool
isValid() const
{
return value_.isValid();
}
void
maybeThrow() const
{
if (not isValid())
throw error::State (failureLog_, lumiera_error_peek());
}
operator RES() const
{
maybeThrow();
return *value_;
}
template<typename TY>
TY
get() const
{
maybeThrow();
return static_cast<TY> (*value_);
}
};
class Result;
/**
* Specialisation for signalling success or failure,
* The base case is just to capture success or failure,
* without returning any value result.
*/
template<>
@ -138,23 +87,81 @@ namespace lib {
: failureLog_{reason.what()}
{ }
bool
isValid() const
{
return isnil (failureLog_);
}
operator bool() const { return isValid(); }
bool isValid() const { return isnil (failureLog_); }
void
maybeThrow() const
{
if (not isValid())
throw error::State (failureLog_, lumiera_error_peek());
throw error::State (failureLog_);
}
};
/**
* Optional Result value or status of some operation.
* It can be created for passing a result produced by the operation, or the
* failure to do so. The value can be retrieved by implicit or explicit conversion.
* @throw error::State on any attempt to access the value in case of failure
* @warning this class has a lot of implicit conversions;
* care should be taken when defining functions
* to take Result instances as parameter....
*/
template<typename RES>
class Result
: public Result<void>
{
wrapper::ItemWrapper<RES> value_;
public:
/** mark an invalid/failed result */
Result (string const& failureReason ="no result")
: Result<void>{failureReason}
{ }
/** failed result, with reason given.*/
Result (lumiera::Error const& reason)
: Result<void>{reason}
{ }
/** standard case: valid result */
Result (RES&& value)
: Result<void>{true}
, value_{std::forward<RES> (value)}
{ }
operator RES() const
{
maybeThrow();
return *value_;
}
template<typename TY>
TY
get() const
{
maybeThrow();
return static_cast<TY> (*value_);
}
template<typename MAKE, typename...ARGS>
RES
getOrElse (MAKE&& producer, ARGS ...args)
{
if (isValid())
return *value_;
else
return std::invoke(std::forward<MAKE> (producer), std::forward<ARGS> (args)...);
}
};
template<typename VAL>
Result (VAL&& x) -> Result<VAL>;
} // namespace lib

View file

@ -533,6 +533,11 @@ return: 0
END
TEST "Either-result-or-failure" Result_test <<END
return: 0
END
TEST "ScopedHolder_test" ScopedHolder_test <<END
out: checking ScopedHolder<Dummy>...
out: checking ScopedPtrHolder<Dummy>...

View file

@ -0,0 +1,108 @@
/*
Result(Test) - verify the either-result-or-failure intermediary wrapper
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 result-test.cpp
** unit test \ref Result_test
*/
#include "lib/test/run.hpp"
#include "lib/test/test-helper.hpp"
#include "lib/result.hpp"
#include "lib/util.hpp"
#include <cstdlib>
namespace lib {
namespace test{
using util::isSameObject;
using std::rand;
namespace error = lumiera::error;
using error::LUMIERA_ERROR_FATAL;
using error::LUMIERA_ERROR_STATE; ///////////////////TODO
namespace {
const Literal THE_END = "all dead and hero got the girl";
#define Type(_EXPR_) lib::test::showType<decltype(_EXPR_)>()
}
/***********************************************************************************//**
* @test Verify an intermediary »Either« type, to embody either a successful result,
* or document a failure with encountered exception.
* @see result.hpp
* @see lib::ThreadJoinable usage example
*/
class Result_test
: public Test
{
void
run (Arg)
{
auto happy = Result{THE_END};
CHECK (happy == THE_END);
CHECK (happy.isValid());
CHECK (true == happy);
happy.maybeThrow(); // still alive...
CHECK (Type(happy) == "Result<Literal const&>"_expect);
// Note type deduction: RValue moved into the Result...
auto sequel = Result{Literal{THE_END}};
CHECK (sequel.isValid());
CHECK (Type(sequel) == "Result<Literal>"_expect);
CHECK ( isSameObject (happy.get<Literal const&>(), THE_END));
CHECK (not isSameObject (sequel.get<Literal const&>(), THE_END));
// »Either Right« case : mark as failure
Result<double> facepalm{error::Fatal()};
CHECK (not facepalm.isValid());
VERIFY_ERROR (STATE, (double)facepalm );
VERIFY_ERROR (STATE, facepalm.get<double&>());
VERIFY_ERROR (STATE, facepalm.maybeThrow() );
CHECK (42.0 == facepalm.getOrElse([]{ return 42; }));
}
};
/** Register this test class... */
LAUNCHER (Result_test, "unit common");
}} // namespace lib::test

View file

@ -78947,6 +78947,21 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</p>
</body>
</html></richcontent>
<linktarget COLOR="#fed5c5" DESTINATION="ID_1859841213" ENDARROW="Default" ENDINCLINATION="1276;51;" ID="Arrow_ID_1453893581" SOURCE="ID_1803056303" STARTARROW="None" STARTINCLINATION="1738;-79;"/>
<node COLOR="#ee6e3b" CREATED="1695748033606" HGAP="157" ID="ID_1181956652" MODIFIED="1695748384597" TEXT="(das geht an mich selber)" VSHIFT="13">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
Um das klar zu sagen: zwar hat Christian ein Verbot von &#187;join&#171; angedacht, aber <i>grade in dieser Frage war und bin ich absolut einer Meinung mit ihm. </i>Tats&#228;chlich war Christian sogar zur&#252;ckhaltender (&#8222;man sollte es deprecaten&#8220;) &#8212; und das hat <i>mich</i>&#160; dann auf die Idee gebracht, einen separaten &#187;Joinable&#171;-Wrapper zu schreiben. Und jetzt, viele Jahre sp&#228;ter stehe <i>ich an dem Punkt, </i>da&#223; es kein absehbares Usage-Pattern gibt, und mein Design von damals ungerchtfertigt erscheint.
</p>
</body>
</html></richcontent>
<edge COLOR="#de7676"/>
<font NAME="SansSerif" SIZE="10"/>
</node>
</node>
</node>
<node CREATED="1693788648105" ID="ID_426109467" MODIFIED="1695312840978">
@ -79410,17 +79425,6 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<icon BUILTIN="yes"/>
</node>
</node>
<node CREATED="1695657061352" ID="ID_1954347934" MODIFIED="1695657066365" TEXT="Code-Anordnung">
<node CREATED="1695657067583" ID="ID_1218314116" MODIFIED="1695657096921" TEXT="Problem: weitgehend redundant">
<icon BUILTIN="messagebox_warning"/>
<node CREATED="1695657076966" ID="ID_535675901" MODIFIED="1695657084689" TEXT="aber dennoch variabel"/>
<node CREATED="1695657085260" ID="ID_1430248620" MODIFIED="1695657093224" TEXT="keine VTable erw&#xfc;nsch"/>
</node>
<node CREATED="1695657098101" ID="ID_273999408" MODIFIED="1695657107014" TEXT="L&#xf6;sung: parametrisierbare Basisklasse"/>
<node CREATED="1695657111918" ID="ID_463997820" MODIFIED="1695657217094" TEXT="in Sub-Namespace lib::thread">
<arrowlink COLOR="#6e85a1" DESTINATION="ID_750029588" ENDARROW="Default" ENDINCLINATION="-741;56;" ID="Arrow_ID_1885189676" STARTARROW="None" STARTINCLINATION="-489;0;"/>
</node>
</node>
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1695677839257" ID="ID_1013931122" MODIFIED="1695677867799" TEXT="Problem: R&#xfc;ckgabewert von join()">
<icon BUILTIN="messagebox_warning"/>
<node CREATED="1695677870757" ID="ID_1158604113" MODIFIED="1695678100114" TEXT="war f&#xfc;r die alte Implementierung kein Problem">
@ -79433,8 +79437,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
...da die Implementierung mit einem aktiven Threadpool verbunden war, gab es dort auch eine Managment-Datenstruktur; die Threadpool-Logik hat eine eventuell im Thread noch erkannte Fehlerflag dorthin gespeichert &#8212; und join() konnte diese Fehlerflag dann einfach abholen.
</p>
</body>
</html>
</richcontent>
</html></richcontent>
</node>
<node CREATED="1695678101764" ID="ID_411970965" MODIFIED="1695678328883" TEXT="hat bisher aber nur Fehlerflags abgedeckt, keine Exceptions">
<richcontent TYPE="NOTE"><html>
@ -79446,8 +79449,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
...C kennt ja keine Exceptions &#8212; und der Author des Threadpool-Frameworks hielt Exceptions f&#252;r ein bestenfalls &#252;berfl&#252;ssiges Feature, das es ganz bestimmt nicht rechtfertigt, zus&#228;tzlichen Aufwand zu treiben
</p>
</body>
</html>
</richcontent>
</html></richcontent>
</node>
<node CREATED="1695678330517" ID="ID_1924651405" MODIFIED="1695678362369" TEXT="der R&#xfc;ckgabewert wurde bisher &#xfc;ber einen &#xbb;Either-Typ&#xab; dargestellt">
<richcontent TYPE="NOTE"><html>
@ -79459,8 +79461,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
gemeint ist lib::Result
</p>
</body>
</html>
</richcontent>
</html></richcontent>
</node>
<node CREATED="1695679266329" ID="ID_1299395095" MODIFIED="1695679291989" TEXT="das Feature erscheint mir &#x201e;halbgar&#x201c;">
<node CREATED="1695679293241" ID="ID_782789148" MODIFIED="1695679338571" TEXT="Exceptions k&#xf6;nnten strukturierte Diagnose-Info transportieren"/>
@ -79476,8 +79477,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
...und zwar im Besonderen, wenn man in einer &#187;reaping-loop&#171; alle Kind-Threads ernten m&#246;chte; dann w&#252;rde nur ein Fehler ausgeworfen, und die weiteren Kinder bleiben ungeerntet (und terminieren jetzt, mit der C++14-L&#246;sung sogar das Programm)
</p>
</body>
</html>
</richcontent>
</html></richcontent>
</node>
<node CREATED="1695679527561" ID="ID_1584831418" MODIFIED="1695679550241" TEXT="und das Naheliegendste, n&#xe4;mlich das Abholen von Ergebnissen ist nicht implementiert"/>
<node CREATED="1695679555637" ID="ID_1907767140" MODIFIED="1695679621871" TEXT="zu allem &#xdc;berfluss...">
@ -79504,9 +79504,10 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#ccb59b" COLOR="#6e2a38" CREATED="1695680809244" ID="ID_530073405" MODIFIED="1695680823462" TEXT="YAGNI &#x27f9; das Feature wird aufgegeben">
<font ITALIC="true" NAME="SansSerif" SIZE="14"/>
<icon BUILTIN="yes"/>
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1695680809244" ID="ID_530073405" MODIFIED="1695749285205" TEXT="YAGNI &#x27f9; aufgeben?">
<font NAME="SansSerif" SIZE="14"/>
<icon BUILTIN="help"/>
<icon BUILTIN="stop-sign"/>
<node CREATED="1695680837800" ID="ID_556594754" MODIFIED="1695680932789" TEXT="das ganze Thread-Join-Ged&#xf6;ns hat sich generell als nicht so gl&#xfc;cklich herausgestellt">
<richcontent TYPE="NOTE"><html>
<head>
@ -79517,8 +79518,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
Das ist ein klassischer Fall f&#252;r ein Feature, das zu Beginn so offensichtlich und irre n&#252;tzlich aussieht &#8212; dann aber in der Realit&#228;t nicht wirklich &#8222;fliegt&#8220;
</p>
</body>
</html>
</richcontent>
</html></richcontent>
</node>
<node CREATED="1695680933859" ID="ID_9664587" MODIFIED="1695680967629">
<richcontent TYPE="NODE"><html>
@ -79530,8 +79530,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
heute bevorzugt man f&#252;r &#228;hnliche Anforderungen das <b>Future / Promise</b>&#160;- Konstrukt
</p>
</body>
</html>
</richcontent>
</html></richcontent>
</node>
<node CREATED="1695680969567" ID="ID_854612368" MODIFIED="1695681002718" TEXT="oder man sammelt gleich Ergebnis-Nachrichten in einer Lock-free-Queue"/>
<node CREATED="1695681067025" ID="ID_1829988819" MODIFIED="1695681202200" TEXT="Fehler in Threads k&#xf6;nnen im Einzelfall sehr relevant sein &#x2014; das ist aber nix Generisches">
@ -79544,13 +79543,217 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
Denn tats&#228;chlich sind aufgetretene Fehler dann ehr schon eine Form von Zustand, den man mit einem speziellen Protokoll im Thread-Objekt erfassen und nach dem join() abfragen sollte; so kann man auch die Ergebnisse mehrerer Threads korrekt kombinieren
</p>
</body>
</html>
</richcontent>
</html></richcontent>
<icon BUILTIN="yes"/>
</node>
<node CREATED="1695681207655" ID="ID_1998022902" MODIFIED="1695681463386" TEXT="brauche dann aber einen Ersatz f&#xfc;r die zwei Tests">
<arrowlink COLOR="#b65b7a" DESTINATION="ID_478666570" ENDARROW="Default" ENDINCLINATION="41;-72;" ID="Arrow_ID_1595086726" STARTARROW="None" STARTINCLINATION="-427;24;"/>
</node>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1695747229306" ID="ID_1952535260" MODIFIED="1695747238936" TEXT="am n&#xe4;chsten Tag dann wieder Zweifel">
<icon BUILTIN="smily_bad"/>
<node BACKGROUND_COLOR="#d7cfb0" COLOR="#3fa41b" CREATED="1695747248047" ID="ID_1584465729" MODIFIED="1695747828936" TEXT="&#xbb;es ist so sch&#xf6;ne Physik&#xab;"/>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1695748401477" ID="ID_1245905649" MODIFIED="1695748490377" TEXT="ohne einen R&#xfc;ckgabewert wirkt die &#xbb;Joinable&#xab;-Variante insgesamt fragw&#xfc;rdig">
<linktarget COLOR="#8c5869" DESTINATION="ID_1245905649" ENDARROW="Default" ENDINCLINATION="10;123;" ID="Arrow_ID_155554446" SOURCE="ID_1803056303" STARTARROW="None" STARTINCLINATION="129;7;"/>
<icon BUILTIN="stop-sign"/>
</node>
<node COLOR="#641f4f" CREATED="1695748527108" ID="ID_964369484" MODIFIED="1695748573531" TEXT="Policy-Design ungerechtfertigt">
<icon BUILTIN="broken-line"/>
</node>
<node COLOR="#9b0f8e" CREATED="1695748885164" ID="ID_1477111545" MODIFIED="1695749387232" TEXT="verdammt noch einmal!!">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
<b>Knoten durchhauen</b>!
</p>
<p>
Warum qu&#228;le ich mich damit herum, was ich k&#252;nftig d&#252;rfen darf, und was unangemessen w&#228;re? Meine Einstellung ist doch, da&#223; eine Library strukturieren sollte, aber nicht vorgreifen und bestimmen. Wenn die letzten 10 Jahre eines gezeigt haben, dann den Umstand, da&#223; der Thread-Wrapper vor <b>allem f&#252;r Tests</b>&#160;verwendet wird. Und genau da gelten die ganzen Performance- und Architektur-&#220;berlegungen &#252;berhaupt nicht; sondern es kommt auf die den Umst&#228;nden entsprechende, gradlinige Formulierung im Testcode an. Und da k&#246;nnte <i>unter Umst&#228;nden </i>Fork-Join genau die KISS-L&#246;sung sein. Insofern w&#228;re das Design bereits nahezu gelungen: es trennt einen intendierten Standardfall ab, l&#228;&#223;t aber sonst alle T&#252;ren offen....
</p>
</body>
</html></richcontent>
<edge COLOR="#9a3d6d"/>
<arrowlink COLOR="#dd26d2" DESTINATION="ID_1308996711" ENDARROW="Default" ENDINCLINATION="194;-5;" ID="Arrow_ID_1982134212" STARTARROW="None" STARTINCLINATION="172;16;"/>
<font NAME="SansSerif" SIZE="15"/>
<icon BUILTIN="smiley-angry"/>
</node>
<node COLOR="#435e98" CREATED="1695749294374" HGAP="18" ID="ID_1090986395" MODIFIED="1695749396815" TEXT="besser machen!!!!" VSHIFT="3">
<font NAME="SansSerif" SIZE="9"/>
<icon BUILTIN="ksmiletris"/>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1695749704247" ID="ID_827179831" MODIFIED="1695749714510" TEXT="R&#xfc;ckgabewert per lib::Result">
<icon BUILTIN="flag-yellow"/>
<node CREATED="1695749715525" ID="ID_914625209" MODIFIED="1695749847745" TEXT="das ist ein Either-Typ">
<icon BUILTIN="yes"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1695749719789" ID="ID_1636786367" MODIFIED="1695749844541" TEXT="diesen modernisieren">
<icon BUILTIN="flag-yellow"/>
<node CREATED="1695749730882" ID="ID_720335444" MODIFIED="1695749749631" TEXT="sollte einen std::exception_ptr nehmen">
<icon BUILTIN="idea"/>
<node CREATED="1695749758416" ID="ID_1018098640" MODIFIED="1695749764076" TEXT="dieser dient als Varianten-Flag"/>
<node CREATED="1695749764647" ID="ID_160637410" MODIFIED="1695749781209">
<richcontent TYPE="NODE"><html>
<head>
</head>
<body>
<p>
und kann zugleich <b>jedwede</b>&#160;Exception halten
</p>
</body>
</html></richcontent>
</node>
</node>
<node CREATED="1695749796803" ID="ID_1154699124" MODIFIED="1695749823763" TEXT="API sollte k&#xfc;nftig eine Exception als &#xbb;right value&#xab; nehmen"/>
<node CREATED="1695749825847" ID="ID_1357368217" MODIFIED="1695749841931">
<richcontent TYPE="NODE"><html>
<head>
</head>
<body>
<p>
und ansonsten aber <i>left-biassed</i>&#160;sein
</p>
</body>
</html></richcontent>
</node>
</node>
</node>
</node>
<node CREATED="1695657061352" ID="ID_1954347934" MODIFIED="1695747338448" TEXT="Code-Anordnung">
<icon BUILTIN="messagebox_warning"/>
<node CREATED="1695657067583" ID="ID_1218314116" MODIFIED="1695657096921" TEXT="Problem: weitgehend redundant">
<icon BUILTIN="messagebox_warning"/>
<node CREATED="1695657076966" ID="ID_535675901" MODIFIED="1695657084689" TEXT="aber dennoch variabel"/>
<node CREATED="1695657085260" ID="ID_1430248620" MODIFIED="1695657093224" TEXT="keine VTable erw&#xfc;nscht"/>
</node>
<node CREATED="1695657098101" ID="ID_273999408" MODIFIED="1695657107014" TEXT="L&#xf6;sung: parametrisierbare Basisklasse"/>
<node CREATED="1695657111918" ID="ID_463997820" MODIFIED="1695657217094" TEXT="in Sub-Namespace lib::thread">
<arrowlink COLOR="#6e85a1" DESTINATION="ID_750029588" ENDARROW="Default" ENDINCLINATION="-741;56;" ID="Arrow_ID_1885189676" STARTARROW="None" STARTINCLINATION="-489;0;"/>
</node>
<node CREATED="1695747369039" ID="ID_1807166092" MODIFIED="1695747532236" TEXT="immer noch unklar und problematisch">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
Es w&#228;re zwar so irgendwie hinzubekommen &#8212; aber <i>weit entfernt von einem guten Design.</i>
</p>
<p>
Ich baue hier eine auf Dauer angelegte L&#246;sung, die auch sichtbar ist und in Frage gestellt werden wird!
</p>
</body>
</html>
</richcontent>
<node CREATED="1695747533905" ID="ID_990711241" MODIFIED="1695747552434" TEXT="der bool-Template-Parameter wirkt unbeholfen"/>
<node CREATED="1695747554262" ID="ID_1830373313" MODIFIED="1695747660353" TEXT="dadurch ist es erschwert, Grundbausteine in eine CPP-Unit wegzupacken">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
hab das gestern versucht &#8212; so kann das nicht stehen bleiben, das ist ja l&#228;cherlich (brauche explizite Template-Instantiierung) &#8212; zumindest solange wir keine C++-Module verwenden (C++20)
</p>
</body>
</html>
</richcontent>
</node>
<node CREATED="1695747673046" ID="ID_1466067755" MODIFIED="1695747692667">
<richcontent TYPE="NODE"><html>
<head>
</head>
<body>
<p>
die Code-Anordnung&#160;<i>hat keinen Flow</i>
</p>
</body>
</html>
</richcontent>
<font NAME="SansSerif" SIZE="12"/>
</node>
<node CREATED="1695747880669" ID="ID_1803056303" MODIFIED="1695748482205" TEXT="die erzwungene &#xbb;Joinable&#xab;-Variante wirkt mutwillig">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
Ich habe doch selber oben diese Prinzipien formuliert: eine Library-L&#246;sung sollte nicht mutwillig beschr&#228;nken, sondern eine sinnvolle Gliederung anbieten...
</p>
</body>
</html>
</richcontent>
<arrowlink COLOR="#fed5c5" DESTINATION="ID_1859841213" ENDARROW="Default" ENDINCLINATION="1276;51;" ID="Arrow_ID_1453893581" STARTARROW="None" STARTINCLINATION="1738;-79;"/>
<arrowlink COLOR="#8c5869" DESTINATION="ID_1245905649" ENDARROW="Default" ENDINCLINATION="10;123;" ID="Arrow_ID_155554446" STARTARROW="None" STARTINCLINATION="129;7;"/>
</node>
</node>
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1695748592388" ID="ID_836153579" MODIFIED="1695748632222">
<richcontent TYPE="NODE"><html>
<head>
</head>
<body>
<p>
also vielleicht doch <b>Policy-based-Design</b>?
</p>
</body>
</html>
</richcontent>
<icon BUILTIN="help"/>
<node CREATED="1695748635886" ID="ID_859201330" MODIFIED="1695748676734" TEXT="aaber ... dann wird ja alles noch umst&#xe4;ndlicher">
<icon BUILTIN="clanbomber"/>
</node>
<node CREATED="1695748653462" ID="ID_763671935" MODIFIED="1695748671048" TEXT="dann kann ich nicht mehr die Konstruktor-Varianten erben">
<icon BUILTIN="messagebox_warning"/>
</node>
<node CREATED="1695748787634" ID="ID_1593689414" MODIFIED="1695748855312">
<richcontent TYPE="NODE"><html>
<head>
</head>
<body>
<p>
&#10233; wenn &#252;berhaupt, m&#252;&#223;te die Policy einen <i>mittleren Binding-Layer </i>bilden
</p>
</body>
</html>
</richcontent>
</node>
<node BACKGROUND_COLOR="#ccb59b" COLOR="#6e2a38" CREATED="1695749319298" ID="ID_1308996711" MODIFIED="1695749370296" TEXT="eine Policy f&#xfc;r Fehlerbehandlung + R&#xfc;ckgabewert + Join w&#xe4;re gerechtfertigt">
<linktarget COLOR="#dd26d2" DESTINATION="ID_1308996711" ENDARROW="Default" ENDINCLINATION="194;-5;" ID="Arrow_ID_1982134212" SOURCE="ID_1477111545" STARTARROW="None" STARTINCLINATION="172;16;"/>
<font ITALIC="true" NAME="SansSerif" SIZE="14"/>
<icon BUILTIN="yes"/>
</node>
<node COLOR="#435e98" CREATED="1695749427868" ID="ID_1042254250" MODIFIED="1695749686462" TEXT="L&#xf6;sung">
<font BOLD="true" NAME="SansSerif" SIZE="12"/>
<icon BUILTIN="forward"/>
<node CREATED="1695749436922" ID="ID_1431671531" MODIFIED="1695749455500" TEXT="Unterlage: &#xbb;ThreadWrapper&#xab;"/>
<node CREATED="1695749456164" ID="ID_1054598766" MODIFIED="1695749478601" TEXT="Mittelschicht: &#xbb;ThreadLifecycle&#xab;">
<node CREATED="1695749538333" ID="ID_1896384393" MODIFIED="1695749549565" TEXT="definiert alle Konstruktoren"/>
<node CREATED="1695749531182" ID="ID_1148976245" MODIFIED="1695749537508" TEXT="definiert den Destruktor"/>
<node CREATED="1695749523263" ID="ID_1222427695" MODIFIED="1695749551050" TEXT="f&#xfc;hrt eine Policy ein"/>
<node CREATED="1695749552627" ID="ID_573772960" MODIFIED="1695749648141">
<richcontent TYPE="NODE"><html>
<head>
</head>
<body>
<p>
Policy <font size="5"><b>&#10549;</b></font>&#160;<font color="#07097c" face="Monospaced">main&lt;POL,FUN,ARGS...&gt;</font>
</p>
</body>
</html>
</richcontent>
</node>
</node>
<node CREATED="1695749669204" ID="ID_1950929730" MODIFIED="1695749680246" TEXT="Front-End: wie bisher"/>
</node>
</node>
</node>
</node>