Error integration: error::Flag as subclass of State. Wrapped throw

This commit is contained in:
Fischlurch 2010-02-13 20:56:41 +01:00
parent acd0671390
commit 90d311dc1d
5 changed files with 134 additions and 69 deletions

View file

@ -192,7 +192,6 @@ namespace backend {
lumiera_thread_join (thread_);
thread_ = 0;
TODO("check this, is error::State approbiate or do we want Runtime as thrown by throwOnError()");
if (errorInOtherThread)
throw lumiera::error::State ("Thread terminated with error:", errorInOtherThread);
}

View file

@ -2,7 +2,7 @@
ERROR.hpp - Lumiera Exception Interface
Copyright (C) Lumiera.org
2008, Hermann Vosseler <Ichthyostega@web.de>
2008-2010 Hermann Vosseler <Ichthyostega@web.de>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
@ -49,9 +49,9 @@ namespace lumiera {
class Error : public std::exception
{
public:
Error (string description="", const char* id=LUMIERA_ERROR_EXCEPTION) throw();
Error (string description="", const char* const id=LUMIERA_ERROR_EXCEPTION) throw();
Error (std::exception const& cause,
string description="", const char* id=LUMIERA_ERROR_EXCEPTION) throw();
string description="", const char* const id=LUMIERA_ERROR_EXCEPTION) throw();
Error (const Error&) throw();
virtual ~Error () throw() {};
@ -97,8 +97,7 @@ namespace lumiera {
/* === Exception Sub-categories === */
namespace error
{
namespace error {
/** global function for handling unknown exceptions
* encountered at functions declaring not to throw
@ -117,6 +116,7 @@ namespace lumiera {
LUMIERA_ERROR_DECLARE (FATAL ); ///< unable to cope with, internal logic floundered
LUMIERA_ERROR_DECLARE (CONFIG ); ///< execution aborted due to misconfiguration
LUMIERA_ERROR_DECLARE (STATE ); ///< unforeseen internal state
LUMIERA_ERROR_DECLARE (FLAG ); ///< non-cleared lumiera errorstate from C code
LUMIERA_ERROR_DECLARE (INVALID ); ///< invalid input or parameters encountered
LUMIERA_ERROR_DECLARE (EXTERNAL ); ///< failure in external service the application relies on
LUMIERA_ERROR_DECLARE (ASSERTION); ///< assertion failure
@ -125,7 +125,6 @@ namespace lumiera {
LUMIERA_ERROR_DECLARE (WRONG_TYPE); ///< runtime type mismatch
LUMIERA_ERROR_DECLARE (ITER_EXHAUST); ///< end of sequence reached
LUMIERA_ERROR_DECLARE (BOTTOM_VALUE); ///< invalid or NIL value
LUMIERA_ERROR_DECLARE (RUNTIME); ///< generic runtime error, will be overridden by id
/** Macro for creating derived exception classes properly
@ -143,7 +142,7 @@ namespace lumiera {
const char* id=_ID_) throw() \
: PARENT (description, id) {} \
\
CLASS (std::exception& cause, \
CLASS (std::exception const& cause, \
std::string description="", \
const char* id=_ID_) throw() \
: PARENT (cause, description, id) {} \
@ -154,30 +153,59 @@ namespace lumiera {
LUMIERA_EXCEPTION_DECLARE (Fatal, Logic, LUMIERA_ERROR_FATAL);
LUMIERA_EXCEPTION_DECLARE (Config, Error, LUMIERA_ERROR_CONFIG);
LUMIERA_EXCEPTION_DECLARE (State, Error, LUMIERA_ERROR_STATE);
LUMIERA_EXCEPTION_DECLARE (Flag, State, LUMIERA_ERROR_FLAG);
LUMIERA_EXCEPTION_DECLARE (Invalid, Error, LUMIERA_ERROR_INVALID);
LUMIERA_EXCEPTION_DECLARE (External, Error, LUMIERA_ERROR_EXTERNAL);
LUMIERA_EXCEPTION_DECLARE (Runtime, Error, LUMIERA_ERROR_RUNTIME);
/** install our own handler for undeclared exceptions. Will be
* called automatically ON_BASIC_INIT when linking exception.cpp */
void install_unexpectedException_handler ();
/** @return error detail-info if currently set, a default message else */
const char* detailInfo ();
} // namespace error
/**
* Throw a 'Runtime' error which wraps an existing lumiera error
* no-op when no error is pending. Does not clear the error state.
* Check the lumiera error state, which maybe was set by C-code.
* @throw Errorflag exception to signal an detected lumiera error
* @note specific error code and information is enclosed in
* the raised exception; the error state is \em not cleared.
*/
static inline void throwOnError()
inline void
throwOnError()
{
lumiera_err err = lumiera_error_peek();
if (err)
if (lumiera_err errorFlag =lumiera_error())
{
const char* extra = lumiera_error_extra();
throw error::Runtime(extra?extra:"", err);
}
throw error::Flag( error::detailInfo()
, errorFlag);
} } //causes the error state to be set
/** Check the lumiera error state and throw a specific exception
* in case a non-cleared errorflag is detected. No-op else.
* @throw instance of the lumiera::Error subclass provided as
* template parameter, containing an lumiera::error::Flag
* as root cause to denote the detected error-flag state.
*/
template<class EX>
inline void
maybeThrow(string description)
{
if (lumiera_err errorFlag =lumiera_error())
{
throw EX (error::Flag( error::detailInfo()
, errorFlag)
,description);
} }
template<class EX>
inline void
maybeThrow()
{
maybeThrow<EX>("");
}

View file

@ -34,6 +34,11 @@ using std::exception;
namespace lumiera {
typedef const char* CStr;
typedef const char* const CCStr;
namespace error {
/** the message shown to the user per default
@ -48,18 +53,27 @@ namespace lumiera {
+ typeid(*exception_obj).name() + ")";
}
inline const char*
default_or_given (const char* id)
inline CStr
default_or_given (CCStr id)
{
return id? id : LUMIERA_ERROR_STATE;
}
CStr
detailInfo ()
{
CCStr detailinfo = lumiera_error_extra();
return isnil (detailinfo)? "Lumiera errorstate detected"
: detailinfo;
}
/* constants to be used as error IDs */
LUMIERA_ERROR_DEFINE (LOGIC , "internal logic broken");
LUMIERA_ERROR_DEFINE (FATAL , "floundered");
LUMIERA_ERROR_DEFINE (CONFIG , "misconfiguration");
LUMIERA_ERROR_DEFINE (STATE , "unforeseen state");
LUMIERA_ERROR_DEFINE (FLAG , "non-cleared lumiera errorstate");
LUMIERA_ERROR_DEFINE (INVALID , "invalid input or parameters");
LUMIERA_ERROR_DEFINE (EXTERNAL , "failure in external service");
LUMIERA_ERROR_DEFINE (ASSERTION, "assertion failure");
@ -78,7 +92,7 @@ namespace lumiera {
/** @note we set the C-style errorstate as a side effect */
Error::Error (string description, const char* id) throw()
Error::Error (string description, CCStr id) throw()
: std::exception (),
id_ (error::default_or_given (id)),
msg_ (error::default_usermsg (this)),
@ -90,7 +104,7 @@ namespace lumiera {
Error::Error (std::exception const& cause,
string description, const char* id) throw()
string description, CCStr id) throw()
: std::exception (),
id_ (error::default_or_given (id)),
msg_ (error::default_usermsg (this)),
@ -117,7 +131,7 @@ namespace lumiera {
* If a root cause can be obtained, this will be included in the
* generated output as well.
*/
const char*
CStr
Error::what() const throw()
{
if (isnil (this->what_))
@ -160,13 +174,13 @@ namespace lumiera {
void lumiera_unexpectedException () throw()
{
const char* is_halted
CCStr is_halted
= "### Lumiera halted due to an unexpected Error ###";
std::cerr << "\n" << is_halted << "\n\n";
ERROR (NOBUG_ON, "%s", is_halted);
if (const char * errorstate = lumiera_error ())
if (CCStr errorstate = lumiera_error ())
ERROR (NOBUG_ON, "last registered error was....\n%s", errorstate);
std::terminate();

View file

@ -205,7 +205,9 @@ out: intermediate handler caught: LUMIERA_ERROR_EXTERNAL:failure in external ser
out: caught lumiera::Error: LUMIERA_ERROR_STATE:unforeseen state -- caused by: LUMIERA_ERROR_EXTERNAL:failure in external service \(test-7\).
out: intermediate handler caught: LUMIERA_ERROR_EXTERNAL:failure in external service \(test-8\).....will rethrow as error::State
out: 2nd intermediate handler caught: LUMIERA_ERROR_STATE:unforeseen state -- caused by: LUMIERA_ERROR_EXTERNAL:failure in external service \(test-8\).....will rethrow as error::Config
out: caught lumiera::Error: LUMIERA_ERROR_CONFIG:misconfiguration -- caused by: LUMIERA_ERROR_EXTERNAL:failure in external service \(test-8\).
out: caught lumiera::Error: LUMIERA_ERROR_CONFIG:misconfiguration -- caused by: LUMIERA_ERROR_EXTERNAL:failure in external service \(test-8\)\.
out: caught lumiera::Error: LUMIERA_ERROR_LIFE_AND_UNIVERSE:and everything\? \(what is the answer\?\)\.
out: caught error::Logic: LUMIERA_ERROR_LOGIC:internal logic broken \(the big bang\). -- caused by: LUMIERA_ERROR_LIFE_AND_UNIVERSE:and everything\? \(what is the answer\?\)\.
END

View file

@ -83,6 +83,7 @@ namespace lumiera {
catcher (&test::doubleNestedTh,"test-8");
checkErrorIntegration();
checkErrorFlagPropagation();
checkRootCauseChaining();
}
@ -153,6 +154,27 @@ namespace lumiera {
ASSERT (!lumiera_error ());
}
void detectErrorflag (string) { throwOnError(); }
void detectErrorflagChained (string msg) { maybeThrow<error::Logic>(msg); }
/** @test verify throwing of Exceptions
* based on a non-cleared C error flag
*/
void checkErrorFlagPropagation()
{
lumiera_error_set(LUMIERA_ERROR_LIFE_AND_UNIVERSE, "what is the answer?");
ASSERT (lumiera_error_peek());
catcher (&test::detectErrorflag, "");
ASSERT (LUMIERA_ERROR_LIFE_AND_UNIVERSE == lumiera_error_peek());
catcher (&test::detectErrorflagChained, "the big bang");
ASSERT (LUMIERA_ERROR_LIFE_AND_UNIVERSE == lumiera_error());
}
/** @test the chaining of lumiera::Exception objects
* and the retrieval of the original root cause.
*/