diff --git a/src/lib/iter-stack.hpp b/src/lib/iter-stack.hpp index 1426fb6fa..681233d45 100644 --- a/src/lib/iter-stack.hpp +++ b/src/lib/iter-stack.hpp @@ -62,6 +62,7 @@ #include "lib/util.hpp" #include +#include namespace lib { @@ -131,9 +132,9 @@ namespace lib { } IterStack& - push (TY&& movedElm) + push (TY&& elm) { - this->stateCore().emplace_back (movedElm); + this->stateCore().emplace_back (std::move (elm)); return *this; } @@ -185,9 +186,9 @@ namespace lib { } IterQueue& - feed (TY&& movedElm) + feed (TY&& elm) { - this->stateCore().emplace_front (movedElm); + this->stateCore().emplace_front (std::move (elm)); return *this; } diff --git a/src/proc/control/command-instance-manager.hpp b/src/proc/control/command-instance-manager.hpp index 204555203..ab3cca5c8 100644 --- a/src/proc/control/command-instance-manager.hpp +++ b/src/proc/control/command-instance-manager.hpp @@ -112,6 +112,10 @@ namespace control { void bindAndDispatch (Symbol instanceID, Rec const& argSeq); bool contains (Symbol instanceID) const; + + private: + Command getCloneOrInstance (Symbol); + void handOver (Command&&, Symbol); }; diff --git a/src/proc/control/command-setup.cpp b/src/proc/control/command-setup.cpp index 42675460a..520c23be3 100644 --- a/src/proc/control/command-setup.cpp +++ b/src/proc/control/command-setup.cpp @@ -219,36 +219,64 @@ namespace control { } + /** @internal retrieve either global or local command instance + * When matching a globally defined command, an anonymous clone instance + * will be created. Otherwise a lookup in the local instance table is performed + * and a matching entry is _moved out of the table_. + */ + Command + CommandInstanceManager::getCloneOrInstance (Symbol instanceID) + { + Command instance = Command::maybeGetNewInstance (instanceID); + if (not instance) + { // second attempt: search of a locally "opened" instance + auto entry = table_.find(instanceID); + if (entry == table_.end()) + throw error::Invalid(_Fmt("Command-ID \"%s\" refers neither to a " + "globally registered command definition, " + "nor to an previously opened command instance") + % instanceID + , LUMIERA_ERROR_INVALID_COMMAND); + instance = move(entry->second); + } + ENSURE (instance); + return instance; + } + + + /** @internal hand a command over to the dispatcher */ + void + CommandInstanceManager::handOver (Command&& toDispatch, Symbol cmdID) + { + if (not toDispatch) + throw error::Logic (_Fmt{"attempt to dispatch command instance '%s' " + "without creating a new instance from prototype beforehand"} + % cmdID + , error::LUMIERA_ERROR_LIFECYCLE); + if (not toDispatch.canExec()) + throw error::State (_Fmt{"attempt to dispatch command instance '%s' " + "without binding all arguments properly beforehand"} + % cmdID + , LUMIERA_ERROR_UNBOUND_ARGUMENTS); + + REQUIRE (toDispatch and toDispatch.canExec()); + dispatcher_.enqueue(move (toDispatch)); + ENSURE (not toDispatch); + } + + /** hand over the designated command instance to the dispatcher installed - * on construction. Either the given ID corresponds to a previously "opened" - * local instance (known only to this instance manager). In this case, the - * instance will really be _moved_ over into the dispatcher, which also means - * this instance is no longer "open" for parametrisation. In the other case - * we try to retrieve the given ID from the global CommandRegistry and - * dispatch it, _without removing_ it from the global registry of course. + * on construction. Either the given ID corresponds to a global command definition, + * in which case an anonymous clone copy is created from this command. Alternatively + * the given ID matches a previously "opened" local instance (known only to this + * instance manager). In this case, the instance will really be _moved_ over into + * the dispatcher, which also means this instance is no longer "open" for + * parametrisation. */ void CommandInstanceManager::dispatch (Symbol instanceID) { - auto entry = table_.find(instanceID); - Command fallback; - Command& instance{entry == table_.end()? fallback = Command::get(instanceID) - : entry->second - }; - if (not instance) - throw error::Logic (_Fmt{"attempt to dispatch command instance '%s' " - "without creating a new instance from prototype beforehand"} - % instanceID - , error::LUMIERA_ERROR_LIFECYCLE); - if (not instance.canExec()) - throw error::State (_Fmt{"attempt to dispatch command instance '%s' " - "without binding all arguments properly beforehand"} - % instanceID - , LUMIERA_ERROR_UNBOUND_ARGUMENTS); - - REQUIRE (instance and instance.canExec()); - dispatcher_.enqueue(move (instance)); - ENSURE (not instance); + handOver (getCloneOrInstance (instanceID), instanceID); } @@ -266,7 +294,11 @@ namespace control { void CommandInstanceManager::bindAndDispatch (Symbol instanceID, Rec const& argSeq) { - UNIMPLEMENTED ("fire and forget anonymous instance"); + Command instance{getCloneOrInstance (instanceID)}; + REQUIRE (instance); + instance.bindArg (argSeq); + ENSURE (instance.canExec()); + handOver (move (instance), instanceID); } diff --git a/src/proc/control/command.cpp b/src/proc/control/command.cpp index 9c248ac2e..7d826e82b 100644 --- a/src/proc/control/command.cpp +++ b/src/proc/control/command.cpp @@ -149,6 +149,22 @@ namespace control { } + /** try to access an existing command definition and immediately + * create a new clone copy by calling #newInstance() + * @return when search for this ID was successful, a new anonymous + * command instance based on the same definition, but not registered + * in the global CommandRegistry. Otherwise, when search fails, + * an empty Command instance (as can be tested with `bool` conversion + */ + Command + Command::maybeGetNewInstance (Symbol cmdID) + { + Command cmd = CommandRegistry::instance().queryIndex (cmdID); + return cmd? cmd.newInstance() + : Command{}; + } + + /** @internal just query an existing instance, if any. */ Command Command::fetchDef (Symbol cmdID) diff --git a/src/proc/control/command.hpp b/src/proc/control/command.hpp index 966750f3d..3f5134863 100644 --- a/src/proc/control/command.hpp +++ b/src/proc/control/command.hpp @@ -118,12 +118,15 @@ namespace control { /* === command registry === */ static Command get (Symbol cmdID); static Command get (FuncPtr func); - static bool remove (Symbol cmdID); + static bool remove (Symbol cmdID); /** create a clone definition */ Command storeDef (Symbol newCmdID) const; Command newInstance () const; + static Command maybeGetNewInstance (Symbol cmdID); + + Command (Symbol cmdID) { *this = get (cmdID); } Command() { } ///< undefined command ~Command(); diff --git a/tests/core/proc/control/command-instance-manager-test.cpp b/tests/core/proc/control/command-instance-manager-test.cpp index fc4b85b22..193c0c8d4 100644 --- a/tests/core/proc/control/command-instance-manager-test.cpp +++ b/tests/core/proc/control/command-instance-manager-test.cpp @@ -77,7 +77,7 @@ namespace test { void enqueue (Command&& cmd) override { - queue_.emplace_front (cmd); + queue_.emplace_front (move (cmd)); } public: @@ -147,7 +147,7 @@ namespace test { int r1{rand()%1000}, r2{rand()%2000}; command1::check_ = 0; // commands will add to this on invocation - iManager.bindAndDispatch (COMMAND_PROTOTYPE, {23}); + iManager.bindAndDispatch (COMMAND_PROTOTYPE, Rec{r1}); CHECK (not iManager.contains (COMMAND_PROTOTYPE)); Command com{COMMAND_PROTOTYPE}; @@ -174,6 +174,7 @@ namespace test { Fixture fixture; CommandInstanceManager iManager{fixture}; Symbol instanceID = iManager.newInstance (COMMAND_PROTOTYPE, INVOCATION_ID); + CHECK (iManager.contains (instanceID)); Command cmd = iManager.getInstance (instanceID); CHECK (cmd); @@ -323,7 +324,7 @@ namespace test { VERIFY_ERROR (DUPLICATE_COMMAND, iManager.newInstance (COMMAND_PROTOTYPE, "i1")); VERIFY_ERROR (DUPLICATE_COMMAND, iManager.newInstance (COMMAND_PROTOTYPE, "i2")); - iManager.bindAndDispatch (i1, Rec{-1}); // bind and dispatch i1, thus i1 is ready for new cycle + iManager.bindAndDispatch (i1, {-1}); // bind and dispatch i1, thus i1 is ready for new cycle iManager.newInstance (COMMAND_PROTOTYPE, "i1"); // open new cycle for i1 VERIFY_ERROR (DUPLICATE_COMMAND, iManager.newInstance (COMMAND_PROTOTYPE, "i2")); diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index 121c2a643..31a7d5e30 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -12129,7 +12129,7 @@ - + @@ -12141,6 +12141,7 @@ + @@ -12150,9 +12151,10 @@ + - + @@ -12164,9 +12166,10 @@ + - + @@ -12178,16 +12181,20 @@ + + - + + + @@ -12370,8 +12377,8 @@ - - + + @@ -13047,7 +13054,9 @@ - + + + @@ -13263,7 +13272,28 @@ - + + + + + + + + + + +

+ ...implementiert "für die Zukunft", +

+

+ wenn wir context-bound -Commands verwenden +

+ + +
+ +
+