Error integration: error::Flag as subclass of State. Wrapped throw
This commit is contained in:
parent
acd0671390
commit
90d311dc1d
5 changed files with 134 additions and 69 deletions
|
|
@ -192,7 +192,6 @@ namespace backend {
|
||||||
lumiera_thread_join (thread_);
|
lumiera_thread_join (thread_);
|
||||||
thread_ = 0;
|
thread_ = 0;
|
||||||
|
|
||||||
TODO("check this, is error::State approbiate or do we want Runtime as thrown by throwOnError()");
|
|
||||||
if (errorInOtherThread)
|
if (errorInOtherThread)
|
||||||
throw lumiera::error::State ("Thread terminated with error:", errorInOtherThread);
|
throw lumiera::error::State ("Thread terminated with error:", errorInOtherThread);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
ERROR.hpp - Lumiera Exception Interface
|
ERROR.hpp - Lumiera Exception Interface
|
||||||
|
|
||||||
Copyright (C) Lumiera.org
|
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
|
This program is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the GNU General Public License as
|
modify it under the terms of the GNU General Public License as
|
||||||
|
|
@ -49,9 +49,9 @@ namespace lumiera {
|
||||||
class Error : public std::exception
|
class Error : public std::exception
|
||||||
{
|
{
|
||||||
public:
|
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,
|
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();
|
Error (const Error&) throw();
|
||||||
virtual ~Error () throw() {};
|
virtual ~Error () throw() {};
|
||||||
|
|
@ -97,8 +97,7 @@ namespace lumiera {
|
||||||
|
|
||||||
/* === Exception Sub-categories === */
|
/* === Exception Sub-categories === */
|
||||||
|
|
||||||
namespace error
|
namespace error {
|
||||||
{
|
|
||||||
|
|
||||||
/** global function for handling unknown exceptions
|
/** global function for handling unknown exceptions
|
||||||
* encountered at functions declaring not to throw
|
* 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 (FATAL ); ///< unable to cope with, internal logic floundered
|
||||||
LUMIERA_ERROR_DECLARE (CONFIG ); ///< execution aborted due to misconfiguration
|
LUMIERA_ERROR_DECLARE (CONFIG ); ///< execution aborted due to misconfiguration
|
||||||
LUMIERA_ERROR_DECLARE (STATE ); ///< unforeseen internal state
|
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 (INVALID ); ///< invalid input or parameters encountered
|
||||||
LUMIERA_ERROR_DECLARE (EXTERNAL ); ///< failure in external service the application relies on
|
LUMIERA_ERROR_DECLARE (EXTERNAL ); ///< failure in external service the application relies on
|
||||||
LUMIERA_ERROR_DECLARE (ASSERTION); ///< assertion failure
|
LUMIERA_ERROR_DECLARE (ASSERTION); ///< assertion failure
|
||||||
|
|
@ -125,7 +125,6 @@ namespace lumiera {
|
||||||
LUMIERA_ERROR_DECLARE (WRONG_TYPE); ///< runtime type mismatch
|
LUMIERA_ERROR_DECLARE (WRONG_TYPE); ///< runtime type mismatch
|
||||||
LUMIERA_ERROR_DECLARE (ITER_EXHAUST); ///< end of sequence reached
|
LUMIERA_ERROR_DECLARE (ITER_EXHAUST); ///< end of sequence reached
|
||||||
LUMIERA_ERROR_DECLARE (BOTTOM_VALUE); ///< invalid or NIL value
|
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
|
/** Macro for creating derived exception classes properly
|
||||||
|
|
@ -143,7 +142,7 @@ namespace lumiera {
|
||||||
const char* id=_ID_) throw() \
|
const char* id=_ID_) throw() \
|
||||||
: PARENT (description, id) {} \
|
: PARENT (description, id) {} \
|
||||||
\
|
\
|
||||||
CLASS (std::exception& cause, \
|
CLASS (std::exception const& cause, \
|
||||||
std::string description="", \
|
std::string description="", \
|
||||||
const char* id=_ID_) throw() \
|
const char* id=_ID_) throw() \
|
||||||
: PARENT (cause, description, id) {} \
|
: PARENT (cause, description, id) {} \
|
||||||
|
|
@ -154,30 +153,59 @@ namespace lumiera {
|
||||||
LUMIERA_EXCEPTION_DECLARE (Fatal, Logic, LUMIERA_ERROR_FATAL);
|
LUMIERA_EXCEPTION_DECLARE (Fatal, Logic, LUMIERA_ERROR_FATAL);
|
||||||
LUMIERA_EXCEPTION_DECLARE (Config, Error, LUMIERA_ERROR_CONFIG);
|
LUMIERA_EXCEPTION_DECLARE (Config, Error, LUMIERA_ERROR_CONFIG);
|
||||||
LUMIERA_EXCEPTION_DECLARE (State, Error, LUMIERA_ERROR_STATE);
|
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 (Invalid, Error, LUMIERA_ERROR_INVALID);
|
||||||
LUMIERA_EXCEPTION_DECLARE (External, Error, LUMIERA_ERROR_EXTERNAL);
|
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
|
/** install our own handler for undeclared exceptions. Will be
|
||||||
* called automatically ON_BASIC_INIT when linking exception.cpp */
|
* called automatically ON_BASIC_INIT when linking exception.cpp */
|
||||||
void install_unexpectedException_handler ();
|
void install_unexpectedException_handler ();
|
||||||
|
|
||||||
|
/** @return error detail-info if currently set, a default message else */
|
||||||
|
const char* detailInfo ();
|
||||||
|
|
||||||
} // namespace error
|
} // namespace error
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Throw a 'Runtime' error which wraps an existing lumiera error
|
* Check the lumiera error state, which maybe was set by C-code.
|
||||||
* no-op when no error is pending. Does not clear the error state.
|
* @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 (lumiera_err errorFlag =lumiera_error())
|
||||||
if (err)
|
|
||||||
{
|
{
|
||||||
const char* extra = lumiera_error_extra();
|
throw error::Flag( error::detailInfo()
|
||||||
throw error::Runtime(extra?extra:"", err);
|
, 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>("");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,11 @@ using std::exception;
|
||||||
|
|
||||||
|
|
||||||
namespace lumiera {
|
namespace lumiera {
|
||||||
|
|
||||||
|
typedef const char* CStr;
|
||||||
|
typedef const char* const CCStr;
|
||||||
|
|
||||||
|
|
||||||
namespace error {
|
namespace error {
|
||||||
|
|
||||||
/** the message shown to the user per default
|
/** the message shown to the user per default
|
||||||
|
|
@ -48,18 +53,27 @@ namespace lumiera {
|
||||||
+ typeid(*exception_obj).name() + ")";
|
+ typeid(*exception_obj).name() + ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const char*
|
inline CStr
|
||||||
default_or_given (const char* id)
|
default_or_given (CCStr id)
|
||||||
{
|
{
|
||||||
return id? id : LUMIERA_ERROR_STATE;
|
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 */
|
/* constants to be used as error IDs */
|
||||||
LUMIERA_ERROR_DEFINE (LOGIC , "internal logic broken");
|
LUMIERA_ERROR_DEFINE (LOGIC , "internal logic broken");
|
||||||
LUMIERA_ERROR_DEFINE (FATAL , "floundered");
|
LUMIERA_ERROR_DEFINE (FATAL , "floundered");
|
||||||
LUMIERA_ERROR_DEFINE (CONFIG , "misconfiguration");
|
LUMIERA_ERROR_DEFINE (CONFIG , "misconfiguration");
|
||||||
LUMIERA_ERROR_DEFINE (STATE , "unforeseen state");
|
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 (INVALID , "invalid input or parameters");
|
||||||
LUMIERA_ERROR_DEFINE (EXTERNAL , "failure in external service");
|
LUMIERA_ERROR_DEFINE (EXTERNAL , "failure in external service");
|
||||||
LUMIERA_ERROR_DEFINE (ASSERTION, "assertion failure");
|
LUMIERA_ERROR_DEFINE (ASSERTION, "assertion failure");
|
||||||
|
|
@ -78,7 +92,7 @@ namespace lumiera {
|
||||||
|
|
||||||
|
|
||||||
/** @note we set the C-style errorstate as a side effect */
|
/** @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 (),
|
: std::exception (),
|
||||||
id_ (error::default_or_given (id)),
|
id_ (error::default_or_given (id)),
|
||||||
msg_ (error::default_usermsg (this)),
|
msg_ (error::default_usermsg (this)),
|
||||||
|
|
@ -90,7 +104,7 @@ namespace lumiera {
|
||||||
|
|
||||||
|
|
||||||
Error::Error (std::exception const& cause,
|
Error::Error (std::exception const& cause,
|
||||||
string description, const char* id) throw()
|
string description, CCStr id) throw()
|
||||||
: std::exception (),
|
: std::exception (),
|
||||||
id_ (error::default_or_given (id)),
|
id_ (error::default_or_given (id)),
|
||||||
msg_ (error::default_usermsg (this)),
|
msg_ (error::default_usermsg (this)),
|
||||||
|
|
@ -117,7 +131,7 @@ namespace lumiera {
|
||||||
* If a root cause can be obtained, this will be included in the
|
* If a root cause can be obtained, this will be included in the
|
||||||
* generated output as well.
|
* generated output as well.
|
||||||
*/
|
*/
|
||||||
const char*
|
CStr
|
||||||
Error::what() const throw()
|
Error::what() const throw()
|
||||||
{
|
{
|
||||||
if (isnil (this->what_))
|
if (isnil (this->what_))
|
||||||
|
|
@ -160,13 +174,13 @@ namespace lumiera {
|
||||||
|
|
||||||
void lumiera_unexpectedException () throw()
|
void lumiera_unexpectedException () throw()
|
||||||
{
|
{
|
||||||
const char* is_halted
|
CCStr is_halted
|
||||||
= "### Lumiera halted due to an unexpected Error ###";
|
= "### Lumiera halted due to an unexpected Error ###";
|
||||||
|
|
||||||
std::cerr << "\n" << is_halted << "\n\n";
|
std::cerr << "\n" << is_halted << "\n\n";
|
||||||
ERROR (NOBUG_ON, "%s", is_halted);
|
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);
|
ERROR (NOBUG_ON, "last registered error was....\n%s", errorstate);
|
||||||
|
|
||||||
std::terminate();
|
std::terminate();
|
||||||
|
|
|
||||||
|
|
@ -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: 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: 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: 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
|
END
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -83,6 +83,7 @@ namespace lumiera {
|
||||||
catcher (&test::doubleNestedTh,"test-8");
|
catcher (&test::doubleNestedTh,"test-8");
|
||||||
|
|
||||||
checkErrorIntegration();
|
checkErrorIntegration();
|
||||||
|
checkErrorFlagPropagation();
|
||||||
checkRootCauseChaining();
|
checkRootCauseChaining();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -153,6 +154,27 @@ namespace lumiera {
|
||||||
ASSERT (!lumiera_error ());
|
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
|
/** @test the chaining of lumiera::Exception objects
|
||||||
* and the retrieval of the original root cause.
|
* and the retrieval of the original root cause.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue