Commands: code up implementation of CommandInstanceManager

interesting new twist: we do not even need to decorate with a running number,
since we'll get away with an anonymous command instance, thanks to Command
being a smart-handle
This commit is contained in:
Fischlurch 2017-03-31 23:59:22 +02:00
parent ce71ae1ae4
commit 97e42f75ee
6 changed files with 123 additions and 20 deletions

View file

@ -58,6 +58,7 @@
//#include "proc/common.hpp"
#include <boost/noncopyable.hpp>
#include <unordered_map>
#include <string>
@ -79,6 +80,7 @@ namespace control {
: boost::noncopyable
{
CommandDispatch& dispatcher_;
std::unordered_map<Symbol,Command> table_;
public:
CommandInstanceManager (CommandDispatch&);

View file

@ -144,7 +144,9 @@ namespace control {
/** register a command (Frontend) under the given ID.
* Any previously existing registration is detached from the index
* @throw error::Logic when a registration already exists,
* either under this ID or for the same concrete implementation
* record but with a different ID.
*/
void
track (Symbol cmdID, Command const& commandHandle)

View file

@ -39,9 +39,9 @@
#include "proc/control/command-setup.hpp"
#include "proc/control/command-instance-manager.hpp"
#include "proc/control/command-def.hpp"
//#include "lib/format-string.hpp"
//#include "lib/util.hpp"
#include "lib/symbol.hpp"
#include "lib/format-string.hpp"
#include "lib/util.hpp"
#include <tuple>
#include <utility>
@ -53,9 +53,8 @@ using std::move;
using lib::Symbol;
using lumiera::LifecycleHook;
using lumiera::ON_GLOBAL_INIT;
//using std::string;
//using util::cStr;
//using util::_Fmt;
using std::string;
using util::_Fmt;
namespace proc {
@ -157,26 +156,51 @@ namespace control {
CommandInstanceManager::CommandInstanceManager (CommandDispatch& dispatcher)
: dispatcher_{dispatcher}
, table_{2 * Command::definition_count()}
{ }
/* more to come here...*/
/** @todo more to come here...*/
Symbol
CommandInstanceManager::newInstance (Symbol prototypeID, string invocationID)
{
UNIMPLEMENTED ("CommandInstanceManager::newInstance");
Symbol instanceID{lib::internedString (string{prototypeID}+"."+invocationID)};
Command& instance = table_[instanceID];
if (not instance)
{ // create new clone from the prototype
table_[instanceID] = move (Command::get(prototypeID).newInstance());
ENSURE (instance, "cloning of command prototype failed");
}
return instanceID;
}
/** */
void
CommandInstanceManager::dispatch (Symbol instanceID)
{
UNIMPLEMENTED ("CommandInstanceManager::dispatch");
Command& instance = table_[instanceID];
if (not instance)
throw error::Logic (_Fmt{"attempt to dispatch command instance '%s' "
"without creating a new instance from prototype beforehand"}
% instanceID
, LUMIERA_ERROR_INVALID_COMMAND);
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);
}
bool
CommandInstanceManager::contains (Symbol instanceID) const
{
UNIMPLEMENTED ("CommandInstanceManager::contains");
return util::contains (table_, instanceID);
}

View file

@ -154,7 +154,7 @@ namespace control {
/** @internal make a command ready for use. Typically to be invoked
* through CommandDef during the definition stage, but also used
* for activating clone instances.
* for activating (anonymous) clone instances.
* @param cmdID new ID for creating a separate command registration when provided
* @throw error::Logic when \c this is already activated. */
void
@ -191,7 +191,7 @@ namespace control {
}
/** create independent clone copy of this command */
/** create independent (anonymous) clone copy of this command */
Command
Command::newInstance () const
{

View file

@ -2604,7 +2604,7 @@ This contrastive approach attempts to keep knowledge and definition clustered in
&amp;rarr; CommandSetup
</pre>
</div>
<div title="GuiCommandCycle" creator="Ichthyostega" modifier="Ichthyostega" created="201703031817" modified="201703180039" tags="design operational GuiPattern GuiIntegration draft discuss img" changecount="53">
<div title="GuiCommandCycle" creator="Ichthyostega" modifier="Ichthyostega" created="201703031817" modified="201703312352" tags="design operational GuiPattern GuiIntegration draft discuss img" changecount="54">
<pre>//the process of issuing a session command from the UI//
Within the Lumiera UI, we distinguish between core concerns and the //local mechanics of the UI.// The latter is addressed in the usual way, based on a variation of the [[MVC-Pattern|http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller]]. The UI toolkit set, here the GTK, affords ample ways to express actions and reactions within this framework, where widgets in the presentation view are wired with the corresponding controllers vice versa (GTK terms these connections as //&quot;signals&quot;//, we rely on {{{libSigC++}}} for implementation).
A naive approach would extend these mature mechanisms to also cover the actual functionality of the application. This compelling solution allows quickly to get &quot;something tangible&quot; up and running, yet -- on the long run -- inevitably leads to core concerns being tangled into the presentation layer, which in turn becomes hard to maintain and loaded with &quot;code behind&quot;. Since we are here &quot;for the long run&quot;, we immediately draw the distinction between UI mechanics and core concerns. The latter are, by decree and axiom, required to perform without even an UI layer running. This decision gives rise to the challenge how to form and integrate the invocation of ''core commands'' into the presentation layer.
@ -2643,10 +2643,11 @@ from these use cases, we can derive the //crucial activities for command handlin
* when a command is completely parametrised, it can be invoked. The managing {{{InteractionStateManager}}} knows about this
* on invocation, the ID of the instance is sent via UI-Bus to the {{{CmdInstanceManager}}}
* which in turn removes the instance handle from its registration table and hands it over into the ProcDispatcher
* only the {{{CmdInstanceManager}}} need to know about this actual command instance; there is no global registration
[&lt;img[Access to Session Commands from UI|uml/Command-ui-access.png]]
An immediate consequence is that command instances will be formed //per instance// of InteractionStateManager. Each distinct kind of control system has its own instances, which are kept around, until they are ready for invocation. Each invocation &quot;burns&quot; an instance -- on next access, a new instance ID will be allocated, and the next command invocation cycle starts...
Command instances are like prototypes -- thus each additional level of differentiation will create a clone copy and decorate the basic command ID. Yet this extension process is delegated into multiple stages. Already when a specific InvocationTrail is established, the bare command prototype is specialised, and additionally combined with specific context access rules and maybe even a accessor to retrieve some argument value. The {{{CmdInstanceManager}}} internally maintains and tracks a prepared command instance, supplying a distinct instance number to keep concurrently existing instances apart; instances might be around for an extended period, because commands are enqueued with the ProcDispatcher.
Command instances are like prototypes -- thus each additional level of differentiation will create a clone copy and decorate the basic command ID. Yet this extension process is delegated into multiple stages. Already when a specific InvocationTrail is established, the bare command prototype is specialised, and additionally combined with specific context access rules and maybe even a accessor to retrieve some argument value. The {{{CmdInstanceManager}}} internally maintains and tracks a prepared anonymous command instance within a local registration table. The //smart-handle//-nature of command instance is enough to keep concurrently existing instances apart; instances might be around for an extended period, because commands are enqueued with the ProcDispatcher.
''command definition'':
&amp;rarr; Command scripts are defined in translation units in {{{proc/cmd}}}

View file

@ -11706,6 +11706,14 @@
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1491005426763" ID="ID_1575553505" MODIFIED="1491005475262" TEXT="zu kl&#xe4;ren: duplikate Instanz">
<arrowlink COLOR="#ca978d" DESTINATION="ID_1805144008" ENDARROW="Default" ENDINCLINATION="594;0;" ID="Arrow_ID_191915626" STARTARROW="None" STARTINCLINATION="594;0;"/>
<icon BUILTIN="flag-yellow"/>
<node CREATED="1491005509448" ID="ID_709599195" MODIFIED="1491005512147" TEXT="Fehler?"/>
<node CREATED="1491005514015" ID="ID_66770459" MODIFIED="1491005526578" TEXT="bestehende Instanz &#xfc;berb&#xfc;geln">
<icon BUILTIN="forward"/>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1489191252503" ID="ID_1621107057" MODIFIED="1489191308469" TEXT="#1090 Command access for UI-Elements">
<arrowlink COLOR="#758ba4" DESTINATION="ID_827179653" ENDARROW="Default" ENDINCLINATION="173;83;" ID="Arrow_ID_57938013" STARTARROW="None" STARTINCLINATION="550;-93;"/>
@ -11788,6 +11796,23 @@
</node>
</node>
</node>
<node CREATED="1491005020528" ID="ID_1665806173" MODIFIED="1491005024747" TEXT="zu kl&#xe4;ren">
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1491005025928" ID="ID_1805144008" MODIFIED="1491005470990" STYLE="fork" TEXT="duplikate Instanzen">
<linktarget COLOR="#ca978d" DESTINATION="ID_1805144008" ENDARROW="Default" ENDINCLINATION="594;0;" ID="Arrow_ID_191915626" SOURCE="ID_1575553505" STARTARROW="None" STARTINCLINATION="594;0;"/>
<icon BUILTIN="messagebox_warning"/>
<node CREATED="1491005039414" ID="ID_378645276" MODIFIED="1491005470990" TEXT="mehrfach newInstance() mit gleicher ID"/>
<node CREATED="1491005054595" ID="ID_1987692266" MODIFIED="1491005470990" TEXT="zwei M&#xf6;glichkeiten">
<icon BUILTIN="info"/>
<node CREATED="1491005058931" ID="ID_1108733153" MODIFIED="1491005470990" TEXT="mit neuem Klon &#xfc;berschreiben"/>
<node CREATED="1491005066706" ID="ID_1990482123" MODIFIED="1491005470990" TEXT="Fehler ausl&#xf6;sen"/>
</node>
<node CREATED="1491005071634" ID="ID_178338289" MODIFIED="1491005470990" TEXT="zur Kl&#xe4;rung">
<icon BUILTIN="bell"/>
<node CREATED="1491005078409" ID="ID_1515823316" MODIFIED="1491005470990" TEXT="...mu&#xdf; ich wissen, wie newInstance verwendet wird"/>
<node CREATED="1491005491226" ID="ID_1986906306" MODIFIED="1491005499069" TEXT="und das h&#xe4;ngt von InvocationTrail ab"/>
</node>
</node>
</node>
</node>
<node COLOR="#252298" CREATED="1489546623162" HGAP="-24" ID="ID_1622574347" MODIFIED="1489778039083" TEXT="was wird gebraucht" VSHIFT="21">
<linktarget COLOR="#352c7d" DESTINATION="ID_1622574347" ENDARROW="Default" ENDINCLINATION="39;-3322;" ID="Arrow_ID_1512127407" SOURCE="ID_1401258681" STARTARROW="None" STARTINCLINATION="2000;0;"/>
@ -11812,10 +11837,16 @@
<node CREATED="1489715248861" ID="ID_999876408" MODIFIED="1489715252392" TEXT="brauche">
<node CREATED="1489715276057" ID="ID_878658276" MODIFIED="1489715279093" TEXT="Basis-ID"/>
<node CREATED="1489715297406" ID="ID_601143379" MODIFIED="1489715305201" TEXT="dekoriert durch Invocation-Trail"/>
<node CREATED="1489715320435" ID="ID_1521007439" MODIFIED="1489715325174" TEXT="dekoriert durch laufende Nr"/>
<node CREATED="1489715320435" ID="ID_1521007439" MODIFIED="1491003112168" TEXT="dekoriert durch laufende Nr">
<icon BUILTIN="button_cancel"/>
</node>
<node CREATED="1489715326210" ID="ID_1820734132" MODIFIED="1489715331310" TEXT="guten Hash von diesen"/>
<node CREATED="1489715461992" ID="ID_115322523" MODIFIED="1489715479858" TEXT="&quot;leere&quot; Basis-ID ohne lfdNr"/>
<node CREATED="1489715591582" ID="ID_256884690" MODIFIED="1489715597393" TEXT="inkrement der lfdNr"/>
<node CREATED="1489715461992" ID="ID_115322523" MODIFIED="1491003142993" TEXT="&quot;leere&quot; Basis-ID ohne lfdNr">
<icon BUILTIN="button_cancel"/>
</node>
<node CREATED="1489715591582" ID="ID_256884690" MODIFIED="1491003145193" TEXT="inkrement der lfdNr">
<icon BUILTIN="button_cancel"/>
</node>
</node>
<node CREATED="1489716825126" HGAP="38" ID="ID_969368347" MODIFIED="1489717783561" TEXT="Ans&#xe4;tze" VSHIFT="-1">
<node CREATED="1489716845980" ID="ID_816994670" MODIFIED="1489718875217" TEXT="Command-ID-Token">
@ -11847,6 +11878,25 @@
<node CREATED="1489717807872" ID="ID_1209104496" MODIFIED="1489717818826" TEXT="wir bauen ohnehin den Command-Cycle fest ein"/>
<node CREATED="1489717844003" ID="ID_97055123" MODIFIED="1489717853605" TEXT="letztgenannte L&#xf6;sung ist auf den Punkt"/>
<node CREATED="1489717927279" ID="ID_845301501" MODIFIED="1489717959263" TEXT="Command-ID erf&#xfc;llt keine regulierende Funktion"/>
<node CREATED="1491003369611" ID="ID_854080320" MODIFIED="1491003437055" TEXT="Instanz-Management funktioniert anonym">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
...weil es zu jedem InvocationPath
</p>
<p>
zu jeder Zeit nur eine &quot;offene&quot; Instanz gibt.
</p>
<p>
Also gen&#252;gt es, einen anonymen Klon dieser Instanz zu halten
</p>
</body>
</html>
</richcontent>
</node>
<node CREATED="1489717960331" ID="ID_1849715968" MODIFIED="1489717991603" TEXT="viel wichtiger sind die Aktivierungs-Regeln"/>
</node>
</node>
@ -11923,7 +11973,12 @@
</node>
<node CREATED="1489781392694" ID="ID_1312397991" MODIFIED="1489781396114" TEXT="Festlegungen">
<node CREATED="1489781404925" ID="ID_1918933171" MODIFIED="1489781408881" TEXT="Command-ID">
<node CREATED="1489781409876" ID="ID_1973020417" MODIFIED="1489781419119" TEXT="Bais-ID ist ein string"/>
<node CREATED="1489781409876" ID="ID_1973020417" MODIFIED="1491003215267" TEXT="Basis-ID ist ein Symbol"/>
<node CREATED="1491003215783" ID="ID_1537560721" MODIFIED="1491003227609" TEXT="es wird mit einer Invocation-ID dekoriert"/>
<node CREATED="1491003228101" ID="ID_661472357" MODIFIED="1491003254161" TEXT="wir brauchen keine laufende Nummer">
<icon BUILTIN="idea"/>
</node>
<node CREATED="1491003237108" ID="ID_1167308664" MODIFIED="1491003252150" TEXT="Instance-Management funktioniert anonym"/>
</node>
<node CREATED="1489781426978" ID="ID_1543445405" MODIFIED="1490985671060" TEXT="konkrete Definition">
<icon BUILTIN="button_ok"/>
@ -12057,7 +12112,8 @@
<node CREATED="1490985710963" ID="ID_447657694" MODIFIED="1490985717974" TEXT="keinerlei Lifecycle-Magie"/>
<node CREATED="1490985720722" ID="ID_1386937508" MODIFIED="1490985736292" TEXT="ist nur eine Registry mit etwas Funktionalit&#xe4;t">
<node CREATED="1490986294710" ID="ID_558020871" MODIFIED="1490986301601" TEXT="Comand-IDs dekorieren"/>
<node CREATED="1490986302197" ID="ID_1305641719" MODIFIED="1490986308216" TEXT="fortlaufenden Z&#xe4;hler verwalten">
<node CREATED="1490986302197" ID="ID_1305641719" MODIFIED="1491004967731" TEXT="fortlaufenden Z&#xe4;hler verwalten">
<icon BUILTIN="button_cancel"/>
<node CREATED="1490986345879" ID="ID_1736956933" MODIFIED="1490986393723" TEXT="denn: Dispatch bedeutet Verz&#xf6;gerung">
<richcontent TYPE="NOTE"><html>
<head>
@ -12092,11 +12148,29 @@
</richcontent>
</node>
</node>
<node CREATED="1491004971039" ID="ID_329531567" MODIFIED="1491004978482" TEXT="anonyme Instanz verwalten">
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1491004982341" ID="ID_1956457610" MODIFIED="1491005001237" TEXT="offene Frage: Duplikat &#xfc;berschreiben?">
<icon BUILTIN="help"/>
</node>
<node CREATED="1491005133794" ID="ID_1003096513" MODIFIED="1491005393601" TEXT="vorl&#xe4;ufig &#xfc;berschreibe ich stillschweigend">
<icon BUILTIN="messagebox_warning"/>
</node>
</node>
<node CREATED="1490986309084" ID="ID_1432845924" MODIFIED="1490986319583" TEXT="sicher &#xdc;bergabe an Dispatch">
<node CREATED="1490986320434" ID="ID_1807848022" MODIFIED="1490986324558" TEXT="Dispatch als Closure"/>
<node CREATED="1490986325626" ID="ID_167499115" MODIFIED="1490986333421" TEXT="Exception-Safety!"/>
</node>
</node>
<node CREATED="1491003278638" ID="ID_516679033" MODIFIED="1491003300696" TEXT="Instanz-Management">
<node CREATED="1491003301379" ID="ID_997022970" MODIFIED="1491003305671" TEXT="funktioniert fast von selbst"/>
<node CREATED="1491003306451" ID="ID_1812101347" MODIFIED="1491003314278" TEXT="Command == smart-Handle"/>
<node CREATED="1491003314746" ID="ID_850841535" MODIFIED="1491003350337" TEXT="instanz kann anonym bleiben">
<icon BUILTIN="idea"/>
</node>
<node CREATED="1491003323585" ID="ID_719524765" MODIFIED="1491003347758" TEXT="die lokale Registry h&#xe4;llt sie am Leben">
<icon BUILTIN="info"/>
</node>
</node>
<node CREATED="1490985696821" ID="ID_564026288" MODIFIED="1490985706464" TEXT="wird vom SessionCommandService betrieben"/>
</node>
<node CREATED="1490985748207" ID="ID_1314513556" MODIFIED="1490985751457" TEXT="Instanzbildung">