From 4236d0649a016ae219e26f98cdf30bb7a2d9699f Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Sun, 2 Aug 2009 18:00:03 +0200 Subject: [PATCH] WIP: implement the basic operation of execution pattern --- doc/devel/draw/CommandImpl-1.svg | 677 +++++++++--------- src/lib/error.hpp | 4 +- src/lib/exception.cpp | 2 +- src/proc/control/command-closure.hpp | 3 +- src/proc/control/command.cpp | 22 +- src/proc/control/command.hpp | 10 +- src/proc/control/handling-pattern.cpp | 97 ++- src/proc/control/handling-pattern.hpp | 39 +- src/tool/try.cpp | 5 + .../proc/control/command-use2-test.cpp | 4 +- 10 files changed, 509 insertions(+), 354 deletions(-) diff --git a/doc/devel/draw/CommandImpl-1.svg b/doc/devel/draw/CommandImpl-1.svg index 5e4bc6b1d..84db4bbc3 100644 --- a/doc/devel/draw/CommandImpl-1.svg +++ b/doc/devel/draw/CommandImpl-1.svg @@ -28,8 +28,8 @@ inkscape:pageopacity="0.0" inkscape:pageshadow="2" inkscape:zoom="1.4142136" - inkscape:cx="410.87417" - inkscape:cy="293.93224" + inkscape:cx="420.65266" + inkscape:cy="293.18784" inkscape:document-units="px" inkscape:current-layer="svg2" inkscape:window-width="1668" @@ -68,7 +68,7 @@ GUI + x="164.71809" + y="79.383377">GUI Proc-Layer + style="opacity:1;fill:#f7fceb;fill-opacity:0.71532843999999995;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;color:#000000" /> Command + x="259.46484" + y="240.50024" /> Handle<CommandImpl> + x="326.36804" + y="31.500246" /> + x="460.0473" + y="130.00024" /> CommandImpl CommandRegistry + style="opacity:1;fill:#f7fceb;fill-opacity:0.71532843999999995;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;color:#000000" /> + style="opacity:1;fill:#f7fceb;fill-opacity:0.71532843999999995;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;color:#000000" /> CommandImpl CommandImpl xxx(...) sss() Command::get("name") exec(..) undo(..) bind(..) Index + id="g2594" + style="fill:#eeffda;fill-opacity:0.71532845"> + style="opacity:1;fill:#f7fceb;fill-opacity:0.71532845;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" /> undo def Command @@ -1279,7 +1280,7 @@ sodipodi:role="line">Command @@ -1309,7 +1310,7 @@ + transform="translate(-10.035141,-159.99976)"> + style="opacity:1;fill:#f7fceb;fill-opacity:0.71532843999999995;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;color:#000000" /> ArgumentHolder + transform="translate(-10.035141,-119.81732)"> + style="opacity:1;fill:#f7fceb;fill-opacity:0.71532843999999995;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;color:#000000" /> getHandle(slot) + transform="translate(60.675549,-274.55106)"> @@ -1446,100 +1447,61 @@ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.99999994;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" /> CommandImpl Command Impl - - - - - - - - - - + transform="translate(148.62035,-32.678975)"> undo functor closure - - - arg - - - - arg - - - - arg - - - - arg - ProcDispatcher + + memento + id="tspan5122">HandlingPattern + + + + + + + + + ProcDispatcher - - HandlingPattern + y="196.00024" + x="702.84399" + sodipodi:role="line">memento + + + + arg + + + + arg + + + + arg + + + + arg + + diff --git a/src/lib/error.hpp b/src/lib/error.hpp index ac089518c..b17d808f8 100644 --- a/src/lib/error.hpp +++ b/src/lib/error.hpp @@ -50,7 +50,7 @@ namespace lumiera { { public: Error (string description="", const char* id=LUMIERA_ERROR_EXCEPTION) throw(); - Error (std::exception& cause, + Error (std::exception const& cause, string description="", const char* id=LUMIERA_ERROR_EXCEPTION) throw(); Error (const Error&) throw(); @@ -87,7 +87,7 @@ namespace lumiera { mutable string what_; ///< buffer for generating the detailed description on demand const string cause_; ///< description of first exception encountered in the chain - static const string extractCauseMsg (const std::exception&) throw(); + static const string extractCauseMsg (std::exception const&) throw(); }; diff --git a/src/lib/exception.cpp b/src/lib/exception.cpp index 879862982..a86d796ea 100644 --- a/src/lib/exception.cpp +++ b/src/lib/exception.cpp @@ -87,7 +87,7 @@ namespace lumiera { } - Error::Error (std::exception& cause, + Error::Error (std::exception const& cause, string description, const char* id) throw() : std::exception (), id_ (error::default_or_given (id)), diff --git a/src/proc/control/command-closure.hpp b/src/proc/control/command-closure.hpp index d18aefbf1..b3af1080d 100644 --- a/src/proc/control/command-closure.hpp +++ b/src/proc/control/command-closure.hpp @@ -42,6 +42,7 @@ #include "lib/meta/function-closure.hpp" #include "lib/meta/function-erasure.hpp" #include "lib/meta/tuple.hpp" +#include "lib/format.hpp" #include "lib/util.hpp" //#include @@ -133,7 +134,7 @@ namespace control { ostream& dump (ostream& output) const { - return BASE::dump (output << element() << ','); + return BASE::dump (output << util::str (element()) << ','); } friend bool diff --git a/src/proc/control/command.cpp b/src/proc/control/command.cpp index fd166417d..89ffcb5c9 100644 --- a/src/proc/control/command.cpp +++ b/src/proc/control/command.cpp @@ -224,14 +224,23 @@ namespace control { void Command::undo () { - exec (getDefaultHandlingPattern().howtoUNDO()); + HandlingPattern const& defaultPattern + = HandlingPattern::get (getDefaultHandlingPattern()); + exec (defaultPattern.howtoUNDO()); } void Command::exec (HandlingPattern const& execPattern) { - execPattern.invoke (*this); + execPattern (*this); + } + + + void + Command::exec (HandlingPattern::ID pattID) + { + HandlingPattern::get(pattID) (*this); } @@ -242,13 +251,20 @@ namespace control { } - HandlingPattern const& + HandlingPattern::ID Command::getDefaultHandlingPattern() const { UNIMPLEMENTED ("manage the default command handling pattern"); } + HandlingPattern::ID + Command::setHandlingPattern (HandlingPattern::ID pattID) + { + UNIMPLEMENTED ("manage handling patterns in general"); + } + + template void Command::bindArg (Tuple const& args) diff --git a/src/proc/control/command.hpp b/src/proc/control/command.hpp index 2dae7896b..bf12734e2 100644 --- a/src/proc/control/command.hpp +++ b/src/proc/control/command.hpp @@ -39,6 +39,7 @@ #include "proc/control/command-binding.hpp" #include "proc/control/command-mutation.hpp" #include "proc/control/command-closure.hpp" +#include "proc/control/handling-pattern.hpp" #include "lib/bool-checkable.hpp" #include "lib/handle.hpp" @@ -64,7 +65,6 @@ namespace control { class CommandDef; class CommandImpl; - class HandlingPattern; /** @@ -97,10 +97,16 @@ namespace control { * necessary to get this command invoked properly */ void exec (HandlingPattern const& execPattern); + void exec (HandlingPattern::ID); void execSync (); - HandlingPattern const& getDefaultHandlingPattern() const; + /** @return ID of the execution pattern used by operator() */ + HandlingPattern::ID getDefaultHandlingPattern() const; + + /** define a handling pattern to be used by default + * @return ID of the currently defined default pattern */ + HandlingPattern::ID setHandlingPattern (HandlingPattern::ID); diff --git a/src/proc/control/handling-pattern.cpp b/src/proc/control/handling-pattern.cpp index bb8987ad9..cef91d3e0 100644 --- a/src/proc/control/handling-pattern.cpp +++ b/src/proc/control/handling-pattern.cpp @@ -23,12 +23,24 @@ #include "proc/control/handling-pattern.hpp" +#include "proc/control/command.hpp" + +#include "include/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 -//using boost::str; +#include + + +using boost::str; +using boost::format; +using namespace lumiera; +using util::cStr; +using util::isnil; + namespace control { @@ -39,8 +51,87 @@ namespace control { UNIMPLEMENTED ("Factory for handling patterns"); } + + /** @note: does error handling, but delegates the actual + * execution to the protected (subclass) member */ + ExecResult + HandlingPattern::operator() (Command& command) const + { + TRACE (proc_dbg, "invoking %s...", cStr(command)); + static format err_pre ("Error state detected, %s *NOT* invoked."); + static format err_post ("Error state after %s invocation."); + static format err_fatal ("Execution of %s raised unknown error."); + try + { + Symbol errID_pre = lumiera_error(); + if (errID_pre) + return ExecResult (error::Logic (str (err_pre % command), errID_pre)); + + // Execute the command + perform (command); + + Symbol errID = lumiera_error(); + if (errID) + return ExecResult (error::State (str (err_post % command),errID)); + else + return ExecResult(); + } + + + catch (lumiera::Error& problem) + { + Symbol errID = lumiera_error(); + WARN (command, "Invocation of %s failed: %s", cStr(command), problem.what()); + TRACE (proc_dbg, "Error flag was: %s", errID); + return ExecResult (problem); + } + catch (std::exception& library_problem) + { + Symbol errID = lumiera_error(); + WARN (command, "Invocation of %s failed: %s", cStr(command), library_problem.what()); + TRACE (proc_dbg, "Error flag was: %s", errID); + return ExecResult (error::External (library_problem)); + } + catch (...) + { + Symbol errID = lumiera_error(); + ERROR (command, "Invocation of %s failed with unknown exception; error flag is: %s", cStr(command), errID); + throw error::Fatal (str (err_fatal % command), errID); + } + } - ///////////////////////////////////////////////////////////////////////TODO: is this implementation file actually required?? + HandlingPattern const& + HandlingPattern::howtoUNDO() const + { + return defineUNDO(); + } + + + + /* ====== execution result state object ======= */ + + + /** @note we just grab an retain the error message. + * @todo rather keep the exception object around. */ + ExecResult::ExecResult (lumiera::Error const& problem) + : log_(problem.what()) + { } + + + bool + ExecResult::isValid() const + { + return isnil(log_); + } + + + void + ExecResult::maybeThrow() const + { + 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 1210b5be7..775fc7bb2 100644 --- a/src/proc/control/handling-pattern.hpp +++ b/src/proc/control/handling-pattern.hpp @@ -36,14 +36,17 @@ //#include "pre.hpp" #include "lib/error.hpp" +#include "lib/bool-checkable.hpp" //#include "include/symbol.hpp" //#include +#include namespace control { + using std::string; // using lumiera::Symbol; // using std::tr1::shared_ptr; @@ -51,6 +54,25 @@ namespace control { class Command; + /** + * @todo Type-comment + */ + class ExecResult + : public lib::BoolCheckable + { + const string log_; + + public: + bool isValid() const; + void maybeThrow() const; + + protected: + ExecResult () { } ///< default: command executed successfully + ExecResult (lumiera::Error const&); ///< this result marks a failed execution + + friend class HandlingPattern; + }; + /** * @todo Type-comment */ @@ -70,9 +92,22 @@ namespace control { virtual ~HandlingPattern() {} - virtual void invoke (Command& command) const =0; + /** main functionality: invoke a command, detect errors. + * @return ExecResult object, which might later be used to + * detect errors on execution */ + ExecResult operator() (Command& command) const; + + /** @return HandlingPatter describing how the UNDO operation is to be performed */ + HandlingPattern const& howtoUNDO() const; + + + + protected: + + virtual void perform (Command& command) const =0; + + virtual HandlingPattern const& defineUNDO() const =0; - virtual HandlingPattern const& howtoUNDO() const =0; }; ////////////////TODO currently just fleshing out the API.... diff --git a/src/tool/try.cpp b/src/tool/try.cpp index de0d698f9..de206c43e 100644 --- a/src/tool/try.cpp +++ b/src/tool/try.cpp @@ -16,6 +16,8 @@ #include +#define LUMIERA_LOGGING_CXX +#include "include/logging.h" //#include "include/nobugcfg.h" #include "lib/bool-checkable.hpp" @@ -23,6 +25,7 @@ //#include #include #include +#include using std::rand; @@ -73,6 +76,8 @@ main (int, char**) //(int argc, char* argv[]) } cout << "size=" << sizeof(TestIt1) <<"\n"; + char* horror = 0; + ERROR (all, "note: %s is a horrible thing", horror); cout << "\n.gulp.\n"; diff --git a/tests/components/proc/control/command-use2-test.cpp b/tests/components/proc/control/command-use2-test.cpp index e1fd8c3da..5b6e18be6 100644 --- a/tests/components/proc/control/command-use2-test.cpp +++ b/tests/components/proc/control/command-use2-test.cpp @@ -196,7 +196,9 @@ namespace test { blowUp_ = true; string current = command2::check_.str(); - VERIFY_ERROR( EXTERNAL, com.exec(HandlingPattern::get(SYNC_THROW)) ); + HandlingPattern const& doThrow = HandlingPattern::get(HandlingPattern::SYNC_THROW); + + VERIFY_ERROR( EXTERNAL, com.exec (doThrow) ); ASSERT (command2::check_.str() == current); // we can achieve the same effect,