diff options
| -rw-r--r-- | host/include/uhd/exception.hpp | 33 | ||||
| -rw-r--r-- | host/lib/exception.cpp | 4 | ||||
| -rw-r--r-- | host/tests/error_test.cpp | 35 | 
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  } | 
