From 2aee99f2f336f3ceddbe3d1e3980282dd3eb7e2e Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Tue, 23 Jun 2009 05:54:54 +0200 Subject: [PATCH] WIP working out the details of Mutation and UndoMutation --- src/proc/control/command-closure.hpp | 25 ++++++++++-- src/proc/control/command-mutation.hpp | 56 ++++++++++++++++++++++----- 2 files changed, 68 insertions(+), 13 deletions(-) diff --git a/src/proc/control/command-closure.hpp b/src/proc/control/command-closure.hpp index 4c75feca4..91052aeae 100644 --- a/src/proc/control/command-closure.hpp +++ b/src/proc/control/command-closure.hpp @@ -82,7 +82,7 @@ namespace control { class CmdClosure; - typedef std::tr1::shared_ptr PClo; ///< smart-ptr type used for handling concrete closures + typedef std::tr1::shared_ptr PClosure; ///< smart-ptr type used for handling concrete closures /** Interface */ @@ -91,7 +91,7 @@ namespace control { public: virtual ~CmdClosure() {} - virtual PClo clone() const =0; + virtual PClosure clone() const =0; virtual operator string() const =0; @@ -204,10 +204,10 @@ namespace control { * hidden behind the generic CmdClosure interface * and owned by a shared_ptr PClo. */ - PClo + PClosure clone() const { - return PClo (new Closure (this->params_)); + return PClosure (new Closure (this->params_)); } operator string() const @@ -215,6 +215,23 @@ namespace control { UNIMPLEMENTED ("how to do a string conversion on the variable argument tuple??"); } }; + + + /** + * Special kind of Closure, which \em decorates an existing Closure + * and provides a captured state memento as additional parameter on invocation. + * + * @todo concept isn't clear yet. Multiple MementoClosurese are to decorate a single Closure; + * they have to match and extract the concrete type of the Closure and the provided Memento, + * but the latter needs to be erased immediately. Basically, MementoClosure must be able + * to stand-in for an simple parameter closure. + */ + class MementoClosure + : public CmdClosure + { + + }; + ////////////////TODO currently just fleshing out the API.... diff --git a/src/proc/control/command-mutation.hpp b/src/proc/control/command-mutation.hpp index a17f7973e..63a5019ec 100644 --- a/src/proc/control/command-mutation.hpp +++ b/src/proc/control/command-mutation.hpp @@ -63,21 +63,25 @@ namespace control { class Mutation { CmdFunctor func_; - PClo clo_; + Closure* clo_; public: template Mutation (function const& func) - : func_(func) + : func_(func), + clo_(0) { } virtual ~Mutation() {} virtual Mutation& - close (CmdClosure const& closure) + close (Closure& cmdClosure) { - UNIMPLEMENTED ("accept and store a parameter closure"); + REQUIRE (!clo_, "Lifecycle error: already closed over the arguments"); + REQUIRE (func_, "Param error: not bound to a valid function"); + func_ = cmdClosure->bindArguments(func_); + clo_ = &cmdClosure; return *this; } @@ -85,12 +89,15 @@ namespace control { void operator() () { - UNIMPLEMENTED ("invoke the Mutation functor"); + if (!clo_) + throw lumiera::error::State ("Lifecycle error: function arguments not yet provided", + LUMIERA_ERROR_UNBOUND_ARGUMENTS); + invoke (func_); } /* == diagnostics == */ - typedef PClo Mutation::*_unspecified_bool_type; + typedef PClosure Mutation::*_unspecified_bool_type; /** implicit conversion to "bool" */ operator _unspecified_bool_type() const { return isValid()? &Mutation::clo_ : 0; } // never throws @@ -105,7 +112,20 @@ namespace control { virtual bool isValid () const { - UNIMPLEMENTED ("mutation lifecycle"); + return func_ && clo_; + } + + void + invoke (CmdFunctor & closedFunction) + { + closedFunction.getFun() (); + } + + CmdClosure& + getClosure() ///< Interface for subclasses to access the bound parameters + { + REQUIRE (clo_, "Lifecycle error: function arguments not yet bound"); + return *clo_; } }; @@ -151,15 +171,33 @@ namespace control { Mutation& captureState () { - UNIMPLEMENTED ("invoke the state capturing Functor"); + if (!Mutation::isValid()) + throw lumiera::error::State ("need to bind function arguments prior to capturing undo state", + LUMIERA_ERROR_UNBOUND_ARGUMENTS); + + if (!memento_) // on first invocation we have to close the capture function + captureFunc_ = Mutation::getClosure().bindArguments(func_); + + memento_.reset (new MementoClosure (Mutation::getClosure(), invoke(captureFunc_) )) //////TODO verify exception safety! + + UNIMPLEMENTED ("how to make the inherited operator() use the extended Parameters (including the memento)???"); + return *this; } CmdClosure& getMemento() { - UNIMPLEMENTED ("return the closure serving as memento"); + return *memento_; } + private: + virtual bool + isValid () const + { + return Mutation::isValid() && captureFunc_ && memento_; + } + + }; ////////////////TODO currently just fleshing out the API....