aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--host/include/uhd/exception.hpp33
-rw-r--r--host/lib/exception.cpp4
-rw-r--r--host/tests/error_test.cpp35
3 files changed, 69 insertions, 3 deletions
diff --git a/host/include/uhd/exception.hpp b/host/include/uhd/exception.hpp
index e2a50bf1e..10cd8f501 100644
--- a/host/include/uhd/exception.hpp
+++ b/host/include/uhd/exception.hpp
@@ -32,72 +32,105 @@
*
* The code() provides an error code which allows the application
* the option of printing a cryptic error message from the 1990s.
+ *
+ * The dynamic_clone() and dynamic_throw() methods allow us to:
+ * catch an exception by dynamic type (i.e. derived class), save it,
+ * and later rethrow it, knowing only the static type (i.e. base class),
+ * and then finally to catch it again using the derived type.
+ *
+ * http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2106.html
*/
namespace uhd{
struct UHD_API exception : std::runtime_error{
exception(const std::string &what);
virtual unsigned code(void) const = 0;
+ virtual exception *dynamic_clone(void) const = 0;
+ virtual void dynamic_throw(void) const = 0;
};
struct UHD_API assertion_error : exception{
assertion_error(const std::string &what);
virtual unsigned code(void) const;
+ virtual assertion_error *dynamic_clone(void) const;
+ virtual void dynamic_throw(void) const;
};
struct UHD_API lookup_error : exception{
lookup_error(const std::string &what);
virtual unsigned code(void) const;
+ virtual lookup_error *dynamic_clone(void) const;
+ virtual void dynamic_throw(void) const;
};
struct UHD_API index_error : lookup_error{
index_error(const std::string &what);
virtual unsigned code(void) const;
+ virtual index_error *dynamic_clone(void) const;
+ virtual void dynamic_throw(void) const;
};
struct UHD_API key_error : lookup_error{
key_error(const std::string &what);
virtual unsigned code(void) const;
+ virtual key_error *dynamic_clone(void) const;
+ virtual void dynamic_throw(void) const;
};
struct UHD_API type_error : exception{
type_error(const std::string &what);
virtual unsigned code(void) const;
+ virtual type_error *dynamic_clone(void) const;
+ virtual void dynamic_throw(void) const;
};
struct UHD_API value_error : exception{
value_error(const std::string &what);
virtual unsigned code(void) const;
+ virtual value_error *dynamic_clone(void) const;
+ virtual void dynamic_throw(void) const;
};
struct UHD_API runtime_error : exception{
runtime_error(const std::string &what);
virtual unsigned code(void) const;
+ virtual runtime_error *dynamic_clone(void) const;
+ virtual void dynamic_throw(void) const;
};
struct UHD_API not_implemented_error : runtime_error{
not_implemented_error(const std::string &what);
virtual unsigned code(void) const;
+ virtual not_implemented_error *dynamic_clone(void) const;
+ virtual void dynamic_throw(void) const;
};
struct UHD_API environment_error : exception{
environment_error(const std::string &what);
virtual unsigned code(void) const;
+ virtual environment_error *dynamic_clone(void) const;
+ virtual void dynamic_throw(void) const;
};
struct UHD_API io_error : environment_error{
io_error(const std::string &what);
virtual unsigned code(void) const;
+ virtual io_error *dynamic_clone(void) const;
+ virtual void dynamic_throw(void) const;
};
struct UHD_API os_error : environment_error{
os_error(const std::string &what);
virtual unsigned code(void) const;
+ virtual os_error *dynamic_clone(void) const;
+ virtual void dynamic_throw(void) const;
};
struct UHD_API system_error : exception{
system_error(const std::string &what);
virtual unsigned code(void) const;
+ virtual system_error *dynamic_clone(void) const;
+ virtual void dynamic_throw(void) const;
};
/*!
diff --git a/host/lib/exception.cpp b/host/lib/exception.cpp
index ecb1fe768..ea056bd3b 100644
--- a/host/lib/exception.cpp
+++ b/host/lib/exception.cpp
@@ -27,7 +27,9 @@ exception::exception(const std::string &what):
#define make_exception_impl(name, class, base) \
class::class(const std::string &what): \
base(str(boost::format("%s: %s") % name % what)){} \
- unsigned class::code(void) const{return boost::hash<std::string>()(#class) & 0xfff;}
+ unsigned class::code(void) const{return boost::hash<std::string>()(#class) & 0xfff;} \
+ class *class::dynamic_clone(void) const{return new class(*this);} \
+ void class::dynamic_throw(void) const{throw *this;}
make_exception_impl("AssertionError", assertion_error, exception)
make_exception_impl("LookupError", lookup_error, exception)
diff --git a/host/tests/error_test.cpp b/host/tests/error_test.cpp
index 983f0150c..69437e732 100644
--- a/host/tests/error_test.cpp
+++ b/host/tests/error_test.cpp
@@ -44,7 +44,8 @@ BOOST_AUTO_TEST_CASE(test_assert_has){
std::cout << "The output of the assert_has error:" << std::endl;
try{
uhd::assert_has(vec, 1, "prime");
- }catch(const std::exception &e){
+ }
+ catch(const std::exception &e){
std::cout << e.what() << std::endl;
}
}
@@ -53,7 +54,37 @@ BOOST_AUTO_TEST_CASE(test_assert_throw){
std::cout << "The output of the assert throw error:" << std::endl;
try{
UHD_ASSERT_THROW(2 + 2 == 5);
- }catch(const std::exception &e){
+ }
+ catch(const std::exception &e){
+ std::cout << e.what() << std::endl;
+ }
+}
+
+BOOST_AUTO_TEST_CASE(test_exception_dynamic){
+ uhd::exception *exception_clone;
+
+ //throw an exception and dynamically clone it
+ try{
+ throw uhd::runtime_error("noooooo");
+ }
+ catch(const uhd::exception &e){
std::cout << e.what() << std::endl;
+ exception_clone = e.dynamic_clone();
+ }
+
+ //now we dynamically re-throw the exception
+ try{
+ exception_clone->dynamic_throw();
+ }
+ catch(const uhd::assertion_error &e){
+ BOOST_CHECK(false);
}
+ catch(const uhd::runtime_error &e){
+ BOOST_CHECK(true);
+ }
+ catch(const uhd::exception &e){
+ BOOST_CHECK(false);
+ }
+
+ delete exception_clone; //manual cleanup
}