From: Marc Horowitz Date: Fri, 5 Sep 2014 23:45:24 +0000 (-0700) Subject: expose the class_name in an efficient way X-Git-Tag: v0.22.0~325 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=d7364d7eac8c6667d98332864642cc3ad55e9398;p=folly.git expose the class_name in an efficient way Summary: Add a class_name method, which doesn't need to throw/catch regardless how the exception is captured. Test Plan: exception_wrapper_test Reviewed By: mshneer@fb.com Subscribers: njormrod FB internal diff: D1543596 Tasks: 5025089 Blame Revision: --- diff --git a/folly/ExceptionWrapper.h b/folly/ExceptionWrapper.h index 953ce4d4..d14142f0 100644 --- a/folly/ExceptionWrapper.h +++ b/folly/ExceptionWrapper.h @@ -143,7 +143,7 @@ class exception_wrapper { fbstring what() const { if (item_) { - return exceptionStr(*item_.get()); + return exceptionStr(*item_); } else if (eptr_) { return estr_; } else { @@ -151,10 +151,20 @@ class exception_wrapper { } } + fbstring class_name() const { + if (item_) { + return demangle(typeid(*item_)); + } else if (eptr_) { + return ename_; + } else { + return fbstring(); + } + } + template bool is_compatible_with() const { if (item_) { - return dynamic_cast(getCopied()); + return dynamic_cast(item_.get()); } else if (eptr_) { try { std::rethrow_exception(eptr_); @@ -197,10 +207,12 @@ protected: std::shared_ptr item_; void (*throwfn_)(std::exception*); // Fallback case: store the library wrapper, which is less efficient - // but gets the job done. Also store the the what() string, so we - // can at least get it back out without having to rethrow. + // but gets the job done. Also store exceptionPtr() the name of the + // exception type, so we can at least get those back out without + // having to rethrow. std::exception_ptr eptr_; std::string estr_; + std::string ename_; template friend exception_wrapper make_exception_wrapper(Args&&... args); @@ -212,7 +224,7 @@ private: template static bool with_exception1(F f, T* that) { if (that->item_) { - if (auto ex = dynamic_cast(that->getCopied())) { + if (auto ex = dynamic_cast(that->item_.get())) { f(*ex); return true; } @@ -298,17 +310,10 @@ class try_and_catch : try_and_catch() : Base() {} template - typename std::enable_if::value>::type - assign_eptr(Ex& e) { - this->eptr_ = std::current_exception(); - this->estr_ = exceptionStr(e).toStdString(); - } - - template - typename std::enable_if::value>::type - assign_eptr(Ex& e) { + void assign_eptr(Ex& e) { this->eptr_ = std::current_exception(); this->estr_ = exceptionStr(e).toStdString(); + this->ename_ = demangle(typeid(e)).toStdString(); } template diff --git a/folly/test/ExceptionWrapperTest.cpp b/folly/test/ExceptionWrapperTest.cpp index 5c99c684..785ff13d 100644 --- a/folly/test/ExceptionWrapperTest.cpp +++ b/folly/test/ExceptionWrapperTest.cpp @@ -38,11 +38,15 @@ TEST(ExceptionWrapper, throw_test) { } } -TEST(ExceptionWrapper, boolean) { +TEST(ExceptionWrapper, members) { auto ew = exception_wrapper(); EXPECT_FALSE(bool(ew)); + EXPECT_EQ(ew.what(), ""); + EXPECT_EQ(ew.class_name(), ""); ew = make_exception_wrapper("payload"); EXPECT_TRUE(bool(ew)); + EXPECT_EQ(ew.what(), "std::runtime_error: payload"); + EXPECT_EQ(ew.class_name(), "std::runtime_error"); } TEST(ExceptionWrapper, equals) { @@ -91,6 +95,7 @@ TEST(ExceptionWrapper, try_and_catch_test) { EXPECT_TRUE(bool(ew)); EXPECT_TRUE(ew.getCopied()); EXPECT_EQ(ew.what(), "std::runtime_error: payload"); + EXPECT_EQ(ew.class_name(), "std::runtime_error"); auto rep = ew.is_compatible_with(); EXPECT_TRUE(rep); @@ -111,7 +116,8 @@ TEST(ExceptionWrapper, try_and_catch_test) { throw std::exception(); }); EXPECT_TRUE(bool(ew3)); - EXPECT_NE(ew3.what(), expected); + EXPECT_EQ(ew3.what(), "std::exception: std::exception"); + EXPECT_EQ(ew3.class_name(), "std::exception"); rep = ew3.is_compatible_with(); EXPECT_FALSE(rep); @@ -154,6 +160,7 @@ TEST(ExceptionWrapper, with_exception_test) { }); EXPECT_TRUE(bool(ew)); EXPECT_EQ(ew.what(), "IntException: int == 23"); + EXPECT_EQ(ew.class_name(), "IntException"); ew.with_exception([&](const IntException& ie) { EXPECT_EQ(ie.getInt(), expected); }); @@ -166,6 +173,7 @@ TEST(ExceptionWrapper, with_exception_test) { }); EXPECT_TRUE(bool(ew2)); EXPECT_EQ(ew2.what(), "IntException: int == 23"); + EXPECT_EQ(ew2.class_name(), "IntException"); ew2.with_exception([&](AbstractIntException& ie) { EXPECT_EQ(ie.getInt(), expected); EXPECT_EQ(typeid(ie), typeid(IntException)); @@ -197,6 +205,7 @@ TEST(ExceptionWrapper, non_std_exception_test) { EXPECT_TRUE(bool(ew)); EXPECT_FALSE(ew.is_compatible_with()); EXPECT_EQ(ew.what(), "int"); + EXPECT_EQ(ew.class_name(), "int"); // non-std::exception types are supported, but the only way to // access their value is to explicity rethrow and catch it. try {