From faa0d3e2110bf0f8a0087d08dd621d4d05a5f3f2 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Mon, 9 Oct 2023 02:57:03 +0200 Subject: [PATCH] Library: solved embedding arbitrary argument sequences MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Concept study of the intended solution successful. Can now transparently embed any conceivable functor and an arbitrary argument sequence into a launcher-λ Materialising into a std::tuple> did the trick. --- src/lib/thread.hpp | 57 +++++++++++++------ .../library/thread-wrapper-lifecycle-test.cpp | 8 ++- wiki/thinkPad.ichthyo.mm | 53 +++++++++++------ 3 files changed, 79 insertions(+), 39 deletions(-) diff --git a/src/lib/thread.hpp b/src/lib/thread.hpp index 068eedbcd..383bd9d54 100644 --- a/src/lib/thread.hpp +++ b/src/lib/thread.hpp @@ -107,13 +107,13 @@ #include "lib/error.hpp" #include "lib/nocopy.hpp" #include "include/logging.h" -//#include "lib/builder-qualifier-support.hpp"//////////////////////////TODO #include "lib/format-util.hpp" #include "lib/result.hpp" +#include #include #include -#include +#include namespace util { @@ -122,6 +122,7 @@ namespace util { namespace lib { using std::string; + using std::tuple; @@ -129,9 +130,12 @@ namespace lib { using lib::meta::typeSymbol; using std::forward; + using std::move; using std::decay_t; using std::invoke_result_t; using std::is_constructible; + using std::index_sequence_for; + using std::index_sequence; using std::is_same; using std::__or_; @@ -275,10 +279,8 @@ namespace lib { template class POL, typename RES =void> class ThreadLifecycle : protected POL -// , public lib::BuilderQualifierSupport> { using Policy = POL; -// using Qualifier = typename lib::BuilderQualifierSupport>::Qualifier; template void @@ -339,27 +341,46 @@ namespace lib { ,static_cast (this) ,forward (args)... } { } + - struct ConfigBuilder + + template + static auto + buildLauncher_impl (tuple&& argCopy, index_sequence) + { + return [invocation = move(argCopy)] + (ThreadLifecycle& wrapper) + { + ASSERT (not wrapper.isLive()); + wrapper.threadImpl_ + = std::thread{&ThreadLifecycle::invokeThreadFunction + , &wrapper + , move(std::get (invocation))... }; + }; + } + + template + static auto + buildLauncher (INVO&& ...args) + { + // materialise functor and arguments as copy, to be handed over into the new thread + return buildLauncher_impl (tuple...>{forward (args)...} + ,index_sequence_for{}); + } + + + struct Launch : util::MoveOnly { using Launcher = std::function; Launcher launch; template - ConfigBuilder (FUN&& threadFunction, ARGS&& ...args) - : launch{[=] - (ThreadLifecycle& wrapper) - { - wrapper.threadImpl_ - = std::thread{&ThreadLifecycle::invokeThreadFunction...> - , &wrapper - , std::move(threadFunction) - , std::move(args)... }; - }} + Launch (FUN&& threadFunction, ARGS&& ...args) + : launch{buildLauncher (forward(threadFunction), forward(args)...)} { } - ConfigBuilder&& + Launch&& threadID (string const& id) { launch = [=, chain=std::move(launch)] @@ -372,9 +393,9 @@ namespace lib { } }; - ThreadLifecycle (ConfigBuilder launcher) + ThreadLifecycle (Launch launcher) : Policy{} - { + { launcher.launch (*this); } }; diff --git a/tests/library/thread-wrapper-lifecycle-test.cpp b/tests/library/thread-wrapper-lifecycle-test.cpp index 79c2f036a..6e16b5be5 100644 --- a/tests/library/thread-wrapper-lifecycle-test.cpp +++ b/tests/library/thread-wrapper-lifecycle-test.cpp @@ -91,9 +91,11 @@ namespace test{ SHOW_EXPR(offset) CHECK (offset > 0); - Thread murks{Thread::ConfigBuilder([&]{ - cout << "Hello inner world "< - - + @@ -65368,8 +65367,7 @@ ⟹ Initialisierung von Policy-Bausteinen ist nicht möglich

- - + @@ -65384,8 +65382,7 @@ streng genommen könnte die Thread-Funktion bereits mit der Initialisierung des lib::Result beginnen, während ihr dann die default-Initialisierung dazwischenfunkt

- -
+
@@ -65409,8 +65406,7 @@ da erfahrungsgemäß der OS-Scheduler immer eine gewisse Latenz hat, bis ein Thread tatsächlich ausführbar wird

- - + @@ -65455,8 +65451,7 @@ und per move-assign auf das Handle schiebt.

- - + @@ -65740,15 +65735,14 @@                            .atEnd(terminationHook)});

- - +
- + @@ -65761,14 +65755,13 @@ er bietet als internes API eine Funktion configure(this)

- - +
- + @@ -65781,11 +65774,35 @@ da bin ich schon x-mal darüber gestolpert: man kann per Reference oder per Value initialisieren; was nicht funktioniert ist eine move-Initialisierung, d.h. jeder move-only Argument-Typ macht Probleme. Einziger Ausweg war für mich bisher, die captures explizit zu benennen und per std::forward-assign zu initialisieren

- - +
+ + + + + + + + + + + + +

+ wenn halt Argument-Packs einfach als Typ repräsentierbar wären — aber dem ist nicht so; man muß gegen ein getemplatetes Argument matchen, um aus einem Argument-Pack einen anderen Argument-Pack zu konstruieren +

+ + +
+
+ + + + + +