WIP: implement the basic operation of execution pattern

This commit is contained in:
Fischlurch 2009-08-02 18:00:03 +02:00
parent f2126c0764
commit 4236d0649a
10 changed files with 509 additions and 354 deletions

File diff suppressed because it is too large Load diff

Before

Width:  |  Height:  |  Size: 122 KiB

After

Width:  |  Height:  |  Size: 123 KiB

View file

@ -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();
};

View file

@ -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)),

View file

@ -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 <tr1/memory>
@ -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

View file

@ -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<typename TYPES>
void
Command::bindArg (Tuple<TYPES> const& args)

View file

@ -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);

View file

@ -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 <boost/format.hpp>
//using boost::str;
#include <boost/format.hpp>
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

View file

@ -36,14 +36,17 @@
//#include "pre.hpp"
#include "lib/error.hpp"
#include "lib/bool-checkable.hpp"
//#include "include/symbol.hpp"
//#include <tr1/memory>
#include <string>
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<ExecResult>
{
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....

View file

@ -16,6 +16,8 @@
#include <nobug.h>
#define LUMIERA_LOGGING_CXX
#include "include/logging.h"
//#include "include/nobugcfg.h"
#include "lib/bool-checkable.hpp"
@ -23,6 +25,7 @@
//#include <typeinfo>
#include <boost/format.hpp>
#include <cstdlib>
#include <cstdio>
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";

View file

@ -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,