diff --git a/src/proc/control/command-argument-holder.hpp b/src/proc/control/command-argument-holder.hpp index 4a981588e..351c5a7d5 100644 --- a/src/proc/control/command-argument-holder.hpp +++ b/src/proc/control/command-argument-holder.hpp @@ -45,6 +45,7 @@ //#include "pre.hpp" //#include "lib/error.hpp" +#include "proc/control/command-closure.hpp" //#include //#include @@ -60,38 +61,128 @@ namespace control { // using std::tr1::shared_ptr; // using boost::scoped_ptr; // using std::tr1::function; - using std::ostream; +// using std::ostream; using std::string; + namespace { // empty state marker objects for ArgumentHolder + + template + struct MissingArguments + : Closure + { + typedef typename Closure::ArgTuple ArgTuple; + + MissingArguments () + : Closure (ArgTuple ()) + { } + + private: + virtual bool isValid () const { return false; } + }; + + + template + struct UntiedMemento + : MementoTie + { + typedef typename CommandSignature::CaptureSig SIG_cap; + typedef typename CommandSignature::UndoOp_Sig SIG_undo; + + UntiedMemento() + : MementoTie (function, function) + { } + }; + + } // (END) impl details / empty state marker objects + + /** - * @todo Type-comment + /* Specifically typed CmdClosure, which serves for + * actually allocating storage to hold the command arguments + * and the undo state (memento) for Proc-Layer commands. */ - class CommandArgumentHolder - { - - public: - virtual ~CommandArgumentHolder() { }; - virtual operator string() const =0; - }; - - - inline ostream& operator<< (ostream& os, CommandArgumentHolder const& arg) { return os << string(arg); } - - - - - /** specifically typed subclass used for actual storage */ template class ArgumentHolder - : public CommandArgumentHolder + : public CmdClosure { + Closure arguments_; + MementoTie memento_; - operator string() const { return "bääääh!"; } /////////////////TODO + typedef typename Closure::ArgTuple ArgTuple; + + + /* === proxied CmdClosure interface === */ + + virtual bool isValid () const + { + return bool(arguments_); + } + + + virtual CmdFunctor bindArguments (CmdFunctor& func) + { + if (!arguments_) + throw lumiera::error::State ("Lifecycle error: can't bind functor, " + "command arguments not yet provided", + LUMIERA_ERROR_UNBOUND_ARGUMENTS); + + return arguments_.bindArguments(func); + } + + + virtual operator string() const + { + return "Command-State{ arguments=" + + arguments_? arguments_ : "unbound" + + memento_ ? ", }" : " }" + ; + } + + + public: + /** per default, all data within ArgumentHolder + * is set up in \em empty state. Later on, the + * command arguments are to be provided by #bind , + * whereas the undo functions will be wired by #tie + */ + ArgumentHolder () + : arguments_(MissingArguments) + , memento_(UntiedMemento) + { } + + /** has undo state capturing been invoked? */ + bool + canUndo () + { + return bool(memento_); + } + + + /** store a new argument tuple within this ArgumentHolder, + * discarding and previously stored arguments */ + void + bind (ArgTuple argTup) + { + this->arguments_ = Closure (argTup); + } + + + typedef typename CommandSignature::CaptureSig SIG_cap; + typedef typename CommandSignature::UndoOp_Sig SIG_undo; + + /** create a new memento storage wiring, discarding existing memento state. + * @note any bound undo/capture functions based on the previously held MementoTie + * are silently invalidated; using them will likely cause memory corruption! */ + MementoTie& + tie (function const& undoFunc, + function const& captureFunc) + { + return this->memento_ = MementoTie (undoFunc,captureFunc); + } }; - ////////////////TODO currently just fleshing out the API.... diff --git a/src/proc/control/command-closure.hpp b/src/proc/control/command-closure.hpp index c4ae309fc..34498fe18 100644 --- a/src/proc/control/command-closure.hpp +++ b/src/proc/control/command-closure.hpp @@ -36,6 +36,7 @@ #define CONTROL_COMMAND_CLOSURE_H //#include "pre.hpp" +#include "lib/bool-checkable.hpp" #include "lib/meta/typelist.hpp" #include "lib/meta/function.hpp" #include "lib/meta/function-closure.hpp" @@ -73,7 +74,11 @@ namespace control { using lumiera::typelist::StoreFunction; using lumiera::typelist::NullType; - + + + + LUMIERA_ERROR_DECLARE (UNBOUND_ARGUMENTS); ///< Command functor not yet usable, because arguments aren't bound + /** * A neutral container internally holding @@ -82,19 +87,17 @@ namespace control { typedef FunErasure CmdFunctor; - class CmdClosure; - typedef std::tr1::shared_ptr PClosure; ///< smart-ptr type used for handling concrete closures - /** Interface */ class CmdClosure + : public lib::BoolCheckable { public: virtual ~CmdClosure() {} - virtual PClosure clone() const =0; + virtual operator string() const =0; - virtual operator string() const =0; + virtual bool isValid () const { return true; } virtual CmdFunctor bindArguments (CmdFunctor&) =0; }; @@ -159,7 +162,6 @@ namespace control { { typedef typename FunctionSignature< function >::Args Args; - typedef Tuple ArgTuple; typedef BuildTupleAccessor BuildAccessor; typedef typename BuildAccessor::Accessor ParamStorageTuple; @@ -167,6 +169,8 @@ namespace control { ParamStorageTuple params_; public: + typedef Tuple ArgTuple; + Closure (ArgTuple const& args) : params_(BuildAccessor(args)) { } @@ -195,15 +199,6 @@ namespace control { } - /** create a clone copy of this concrete closure, - * hidden behind the generic CmdClosure interface - * and owned by a shared_ptr PClo. - */ - PClosure - clone() const - { - return PClosure (new Closure (this->params_)); - } operator string() const { diff --git a/src/proc/control/command-mutation.hpp b/src/proc/control/command-mutation.hpp index db3152785..25fa31bc5 100644 --- a/src/proc/control/command-mutation.hpp +++ b/src/proc/control/command-mutation.hpp @@ -73,7 +73,6 @@ namespace control { using std::string; - LUMIERA_ERROR_DECLARE (UNBOUND_ARGUMENTS); ///< Mutation functor not yet usable, because arguments aren't bound /** diff --git a/src/proc/control/command.cpp b/src/proc/control/command.cpp index 0b72a511e..2138ae18c 100644 --- a/src/proc/control/command.cpp +++ b/src/proc/control/command.cpp @@ -39,7 +39,7 @@ namespace control { - LUMIERA_ERROR_DEFINE (UNBOUND_ARGUMENTS, "Mutation functor not yet usable, because arguments aren't bound"); + LUMIERA_ERROR_DEFINE (UNBOUND_ARGUMENTS, "Command mutation functor not yet usable, because arguments aren't bound"); LUMIERA_ERROR_DEFINE (MISSING_MEMENTO, "Undo functor not yet usable, because no undo state has been captured"); diff --git a/tests/components/proc/control/command-argument-test.cpp b/tests/components/proc/control/command-argument-test.cpp index eb3702410..e8e8c485b 100644 --- a/tests/components/proc/control/command-argument-test.cpp +++ b/tests/components/proc/control/command-argument-test.cpp @@ -311,6 +311,7 @@ namespace test { bound_undoFun(); cout << protocol.str() << endl; + // Commands can serve as prototype to be copied.... Args argsCopy (args); bound_captFun(); protocol.seekp(0);