From 248b87f344aa7afe3f48df58efa64c42b3f9196c Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Thu, 1 Oct 2009 13:29:53 +0200 Subject: [PATCH] Basic implementation of HandlingPattern settled for now the ''real implementation'' (integrated with the ProcDispatcher) is still missing, but it's enough to get the tests going --- src/proc/control/handling-pattern.cpp | 30 +----- src/proc/control/handling-pattern.hpp | 35 ++++--- src/proc/control/handling-patterns.hpp | 129 ++++++++++++++----------- 3 files changed, 102 insertions(+), 92 deletions(-) diff --git a/src/proc/control/handling-pattern.cpp b/src/proc/control/handling-pattern.cpp index 439e425dd..91f84d77d 100644 --- a/src/proc/control/handling-pattern.cpp +++ b/src/proc/control/handling-pattern.cpp @@ -25,12 +25,8 @@ #include "proc/control/handling-pattern.hpp" #include "proc/control/handling-patterns.hpp" -#include "lib/symbol.hpp" #include "include/logging.h" #include "lib/util.hpp" -//#include "proc/mobject/mobject-ref.hpp" -//#include "proc/mobject/mobject.hpp" -//#include "proc/mobject/placement.hpp" #include @@ -44,16 +40,14 @@ using util::isnil; namespace control { - /** */ + /** retrieve pre-configured pattern */ HandlingPattern const& HandlingPattern::get (ID id) { - REQUIRE ((0 <= id) && (id < NUM_IDS)); - return getPatternInstance(id); } - + /** @note: does error handling, but delegates the actual * execution to the protected (subclass) member */ ExecResult @@ -69,8 +63,8 @@ namespace control { if (errID_pre) return ExecResult (error::Logic (str (err_pre % command), errID_pre)); - // Execute the command - dispatch (command); + // execute or undo it... + perform (command); Symbol errID = lumiera_error(); if (errID) @@ -103,20 +97,6 @@ namespace control { } - void - HandlingPattern::dispatch (CommandImpl& command) - { - perform (command); - } - - - HandlingPattern const& - HandlingPattern::howtoUNDO() const - { - UNIMPLEMENTED ("yield a handling pattern suitable for UNDOing a command, according to this pattern"); - } - - /* ====== execution result state object ======= */ @@ -141,6 +121,6 @@ namespace control { if (!isnil (log_)) throw error::Logic ("Command execution failed: "+log_); } - + } // namespace control diff --git a/src/proc/control/handling-pattern.hpp b/src/proc/control/handling-pattern.hpp index 34421428a..c2193e7c0 100644 --- a/src/proc/control/handling-pattern.hpp +++ b/src/proc/control/handling-pattern.hpp @@ -22,7 +22,7 @@ /** @file handling-pattern.hpp - ** Pre-defined command execution templates. + ** Pre-defined command execution skeletons. ** Any command can be configured to use a specific handling pattern ** on invocation. Moreover, there is a default handling pattern for commands. ** These patterns define the steps necessary for getting the command actually @@ -46,10 +46,9 @@ //#include "pre.hpp" #include "lib/error.hpp" -#include "lib/bool-checkable.hpp" #include "lib/symbol.hpp" +#include "lib/bool-checkable.hpp" -//#include #include @@ -58,14 +57,16 @@ namespace control { using std::string; using lib::Symbol; -// using std::tr1::shared_ptr; class CommandImpl; /** - * @todo Type-comment + * Result (Status) of command execution. + * It is returned when invoking a HandlingPattern + * and can be used to check for success and/or re-throw + * any Exception encountered during the command execution. */ class ExecResult : public lib::BoolCheckable @@ -83,8 +84,18 @@ namespace control { friend class HandlingPattern; }; + + /** - * @todo Type-comment + * Operation Skeleton how to invoke or undo a command. + * Concrete implementations may be retrieved by ID; + * they range from just invoking the command operations + * straight forward to dispatching with the ProcDispatcher + * or running the command asynchronously in a background thread. + * A HandlingPattern first of all describes how to invoke the + * command operation, but for each pattern it is possible to + * get a special "undo pattern", which, on activation, will + * reverse the effect of the basic pattern. */ class HandlingPattern : public lib::BoolCheckable @@ -114,23 +125,23 @@ namespace control { * detect errors on execution */ ExecResult invoke (CommandImpl& command, Symbol name) const; - /** @return HandlingPatter describing how the UNDO operation is to be performed */ - HandlingPattern const& howtoUNDO() const; + /** @return HandlingPattern describing how the UNDO operation is to be performed */ + HandlingPattern const& howtoUNDO() const { return getUndoPatt(); } virtual bool isValid() const =0; protected: - virtual void dispatch(CommandImpl& command) const; + virtual HandlingPattern const& getUndoPatt() const =0; + virtual void perform (CommandImpl& command) const =0; - virtual void perform (CommandImpl& command) const =0; - virtual void revert (CommandImpl& command) const =0; + virtual void exec (CommandImpl& command) const =0; + virtual void undo (CommandImpl& command) const =0; }; - ////////////////TODO currently just fleshing out the API.... diff --git a/src/proc/control/handling-patterns.hpp b/src/proc/control/handling-patterns.hpp index d8da74f5f..14c7b48d3 100644 --- a/src/proc/control/handling-patterns.hpp +++ b/src/proc/control/handling-patterns.hpp @@ -47,23 +47,72 @@ #include "lib/multifact.hpp" #include "proc/control/handling-pattern.hpp" #include "proc/control/command-impl.hpp" -#include "include/lifecycle.h" -//#include "lib/symbol.hpp" - -//#include -//#include -#include namespace control { namespace { // concrete command handling patterns - - using std::vector; -// using std::string; -// using lib::Symbol; -// using std::tr1::shared_ptr; + + + + + /** + * Handling Pattern Foundation: invoke command directly and without + * any external intervention. This pattern is intended as implementation + * base class, but can be used as-is for unit tests. + */ + class BasicHandlingPattern + : public HandlingPattern + { + bool isValid() const { return true; } + + void + exec (CommandImpl& command) const + { + REQUIRE (command.canExec()); + command.invokeCapture(); + command.invokeOperation(); + } + + void + undo (CommandImpl& command) const + { + REQUIRE (command.canUndo()); + command.invokeUndo(); + } + + /* == invoking operation or undo == */ + + void perform (CommandImpl& command) const { return exec(command); } + + class UndoProxyPattern + : public HandlingPattern + { + BasicHandlingPattern& basePatt_; + + bool isValid() const { return basePatt_.isValid(); } + void exec (CommandImpl& command) const { return basePatt_.exec(command); } + void undo (CommandImpl& command) const { return basePatt_.undo(command); } + + void perform (CommandImpl& command) const { return undo(command); } + HandlingPattern const& getUndoPatt() const { return basePatt_; } + + public: + UndoProxyPattern (BasicHandlingPattern& refPattern) + : basePatt_(refPattern) + { } + }; + + HandlingPattern const& getUndoPatt() const { return standardUndoPattern_; } + UndoProxyPattern standardUndoPattern_; + friend class UndoProxyPattern; + + public: + BasicHandlingPattern() + : standardUndoPattern_(*this) + { } + }; @@ -72,16 +121,16 @@ namespace control { * @todo describe this pattern in more detail.... */ class InvokeSyncNoThrow - : public HandlingPattern + : public BasicHandlingPattern { void - perform (CommandImpl& command) const + exec (CommandImpl& command) const { UNIMPLEMENTED ("actually invoke a command, according to this pattern"); } void - revert(CommandImpl& command) const + undo (CommandImpl& command) const { UNIMPLEMENTED ("actually undo the effect of a command, according to this pattern"); } @@ -100,16 +149,16 @@ namespace control { * @todo describe this pattern in more detail.... */ class InvokeSyncThrow - : public HandlingPattern + : public BasicHandlingPattern { void - perform (CommandImpl& command) const + exec (CommandImpl& command) const { UNIMPLEMENTED ("actually invoke a command, according to this pattern"); } void - revert(CommandImpl& command) const + undo (CommandImpl& command) const { UNIMPLEMENTED ("actually undo the effect of a command, according to this pattern"); } @@ -128,16 +177,16 @@ namespace control { * @todo describe this pattern in more detail.... */ class InvokeAsync - : public HandlingPattern + : public BasicHandlingPattern { void - perform (CommandImpl& command) const + exec (CommandImpl& command) const { UNIMPLEMENTED ("actually invoke a command, according to this pattern"); } void - revert(CommandImpl& command) const + undo (CommandImpl& command) const { UNIMPLEMENTED ("actually undo the effect of a command, according to this pattern"); } @@ -151,37 +200,6 @@ namespace control { - /** - * Handling Pattern: invoke command directly and without any integration - * with other facilities. This pattern is intended to be used for unit tests. - */ - class InvokeDirectly - : public HandlingPattern - { - void - perform (CommandImpl& command) const - { - REQUIRE (command.canExec()); - command.invokeCapture(); - command.invokeOperation(); - } - - void - revert(CommandImpl& command) const - { - REQUIRE (command.canUndo()); - command.invokeUndo(); - } - - bool - isValid() const - { - return true; - } - }; - - - @@ -189,12 +207,13 @@ namespace control { typedef lib::MultiFact HandlingPatternFactory; - /** Table of available command handling patterns */ + /** holds singleton pattern instances by ID */ HandlingPatternFactory patternTable; - HandlingPatternFactory::Singleton holder1 (patternTable, HandlingPattern::SYNC); - HandlingPatternFactory::Singleton holder2 (patternTable, HandlingPattern::SYNC_THROW); - HandlingPatternFactory::Singleton holder3 (patternTable, HandlingPattern::ASYNC); + HandlingPatternFactory::Singleton holder1 (patternTable, HandlingPattern::SYNC); + HandlingPatternFactory::Singleton holder2 (patternTable, HandlingPattern::SYNC_THROW); + HandlingPatternFactory::Singleton holder3 (patternTable, HandlingPattern::ASYNC); + HandlingPatternFactory::Singleton holder4 (patternTable, HandlingPattern::DUMMY); /** access the singleton instance for a given ID */