From f0daf647cd1435d8511b0fd8c64b31ed37e8beb8 Mon Sep 17 00:00:00 2001 From: Yedidya Feldblum Date: Fri, 12 May 2017 14:14:22 -0700 Subject: [PATCH] exception_wrapper::get_object<> Summary: [Folly] `exception_wrapper::get_object<>`. Returns a pointer to the stored object, if the template type parameter is of the right sort. Reviewed By: jsedgwick Differential Revision: D5000720 fbshipit-source-id: 2869439085e8dfb56e6cb439794b03876b7d715c --- folly/ExceptionWrapper-inl.h | 14 ++++++++++++++ folly/ExceptionWrapper.h | 12 ++++++++++++ folly/test/ExceptionWrapperTest.cpp | 22 ++++++++++++++++++++++ 3 files changed, 48 insertions(+) diff --git a/folly/ExceptionWrapper-inl.h b/folly/ExceptionWrapper-inl.h index 99cbd9de..aca35f2c 100644 --- a/folly/ExceptionWrapper-inl.h +++ b/folly/ExceptionWrapper-inl.h @@ -350,6 +350,20 @@ inline std::exception const* exception_wrapper::get_exception() const noexcept { return vptr_->get_exception_(this); } +template +inline Ex* exception_wrapper::get_object() noexcept { + Ex* object{nullptr}; + with_exception([&](Ex& ex) { object = &ex; }); + return object; +} + +template +inline Ex const* exception_wrapper::get_object() const noexcept { + Ex const* object{nullptr}; + with_exception([&](Ex const& ex) { object = &ex; }); + return object; +} + inline std::exception_ptr const& exception_wrapper::to_exception_ptr() noexcept { // Computing an exception_ptr is expensive so cache the result. diff --git a/folly/ExceptionWrapper.h b/folly/ExceptionWrapper.h index a1adfecd..82dfde72 100644 --- a/folly/ExceptionWrapper.h +++ b/folly/ExceptionWrapper.h @@ -457,6 +457,18 @@ class exception_wrapper final { //! \overload std::exception const* get_exception() const noexcept; + //! \returns a pointer to the `Ex` held by `*this`, if it holds an object + //! whose type `From` permits `std::is_convertible`; + //! otherwise, returns `nullptr`. + //! \note This function does not mutate the `exception_wrapper` object. + //! \note This function may cause an exception to be thrown and immediately + //! caught internally, affecting runtime performance. + template + Ex* get_object() noexcept; + //! \overload + template + Ex const* get_object() const noexcept; + //! \return A `std::exception_ptr` that references either the exception held //! by `*this`, or a copy of same. //! \note This function may need to throw an exception to complete the action. diff --git a/folly/test/ExceptionWrapperTest.cpp b/folly/test/ExceptionWrapperTest.cpp index 67f14c5e..fde0e8a9 100644 --- a/folly/test/ExceptionWrapperTest.cpp +++ b/folly/test/ExceptionWrapperTest.cpp @@ -215,6 +215,8 @@ TEST(ExceptionWrapper, with_exception_ptr_empty) { EXPECT_EQ(exception_wrapper::none(), ew.type()); EXPECT_FALSE(bool(ew)); EXPECT_EQ(nullptr, ew.get_exception()); + EXPECT_EQ(nullptr, ew.get_object()); + EXPECT_EQ(nullptr, ew.get_object()); EXPECT_FALSE(ew.has_exception_ptr()); EXPECT_EQ(nullptr, ew.to_exception_ptr()); EXPECT_FALSE(ew.has_exception_ptr()); @@ -230,6 +232,8 @@ TEST(ExceptionWrapper, with_shared_ptr_test) { EXPECT_TRUE(bool(ew)); EXPECT_EQ(typeid(std::runtime_error), ew.type()); EXPECT_NE(nullptr, ew.get_exception()); + EXPECT_NE(nullptr, ew.get_object()); + EXPECT_EQ(nullptr, ew.get_object()); EXPECT_FALSE(ew.has_exception_ptr()); EXPECT_NE(nullptr, ew.to_exception_ptr()); EXPECT_TRUE(ew.has_exception_ptr()); @@ -244,6 +248,8 @@ TEST(ExceptionWrapper, with_shared_ptr_test) { EXPECT_FALSE(bool(ew)); EXPECT_EQ(exception_wrapper::none(), ew.type()); EXPECT_EQ(nullptr, ew.get_exception()); + EXPECT_EQ(nullptr, ew.get_object()); + EXPECT_EQ(nullptr, ew.get_object()); EXPECT_EQ(nullptr, ew.to_exception_ptr()); EXPECT_EQ("", ew.class_name()); EXPECT_EQ("", ew.what()); @@ -258,6 +264,8 @@ TEST(ExceptionWrapper, with_exception_ptr_exn_test) { EXPECT_TRUE(bool(ew)); EXPECT_EQ(typeid(std::runtime_error), ew.type()); EXPECT_NE(nullptr, ew.get_exception()); + EXPECT_NE(nullptr, ew.get_object()); + EXPECT_EQ(nullptr, ew.get_object()); EXPECT_TRUE(ew.has_exception_ptr()); EXPECT_EQ(ep, ew.to_exception_ptr()); EXPECT_TRUE(ew.has_exception_ptr()); @@ -272,6 +280,8 @@ TEST(ExceptionWrapper, with_exception_ptr_exn_test) { EXPECT_FALSE(bool(ew)); EXPECT_EQ(exception_wrapper::none(), ew.type()); EXPECT_EQ(nullptr, ew.get_exception()); + EXPECT_EQ(nullptr, ew.get_object()); + EXPECT_EQ(nullptr, ew.get_object()); EXPECT_EQ(nullptr, ew.to_exception_ptr()); EXPECT_EQ("", ew.class_name()); EXPECT_EQ("", ew.what()); @@ -285,6 +295,8 @@ TEST(ExceptionWrapper, with_exception_ptr_any_test) { auto ew = exception_wrapper(ep, from_eptr(ep)); EXPECT_TRUE(bool(ew)); EXPECT_EQ(nullptr, ew.get_exception()); + EXPECT_EQ(nullptr, ew.get_object()); + EXPECT_NE(nullptr, ew.get_object()); EXPECT_TRUE(ew.has_exception_ptr()); EXPECT_EQ(ep, ew.to_exception_ptr()); EXPECT_TRUE(ew.has_exception_ptr()); @@ -298,6 +310,8 @@ TEST(ExceptionWrapper, with_exception_ptr_any_test) { exception_wrapper(std::move(ew)); EXPECT_FALSE(bool(ew)); EXPECT_EQ(nullptr, ew.get_exception()); + EXPECT_EQ(nullptr, ew.get_object()); + EXPECT_EQ(nullptr, ew.get_object()); EXPECT_EQ(nullptr, ew.to_exception_ptr()); EXPECT_FALSE(ew.has_exception_ptr()); EXPECT_EQ("", ew.class_name()); @@ -311,6 +325,8 @@ TEST(ExceptionWrapper, with_non_std_exception_test) { auto ew = exception_wrapper(folly::in_place, 42); EXPECT_TRUE(bool(ew)); EXPECT_EQ(nullptr, ew.get_exception()); + EXPECT_EQ(nullptr, ew.get_object()); + EXPECT_NE(nullptr, ew.get_object()); EXPECT_FALSE(ew.has_exception_ptr()); EXPECT_EQ("int", ew.class_name()); EXPECT_EQ("int", ew.what()); @@ -326,6 +342,8 @@ TEST(ExceptionWrapper, with_non_std_exception_test) { exception_wrapper(std::move(ew)); EXPECT_FALSE(bool(ew)); EXPECT_EQ(nullptr, ew.get_exception()); + EXPECT_EQ(nullptr, ew.get_object()); + EXPECT_EQ(nullptr, ew.get_object()); EXPECT_EQ(nullptr, ew.to_exception_ptr()); EXPECT_FALSE(ew.has_exception_ptr()); EXPECT_EQ("", ew.class_name()); @@ -340,6 +358,8 @@ TEST(ExceptionWrapper, with_exception_ptr_any_nil_test) { auto ew = exception_wrapper(ep); // concrete type is erased EXPECT_TRUE(bool(ew)); EXPECT_EQ(nullptr, ew.get_exception()); + EXPECT_EQ(nullptr, ew.get_object()); + EXPECT_NE(nullptr, ew.get_object()); EXPECT_EQ(ep, ew.to_exception_ptr()); EXPECT_EQ("", ew.class_name()); // because concrete type is // erased @@ -352,6 +372,8 @@ TEST(ExceptionWrapper, with_exception_ptr_any_nil_test) { exception_wrapper(std::move(ew)); EXPECT_FALSE(bool(ew)); EXPECT_EQ(nullptr, ew.get_exception()); + EXPECT_EQ(nullptr, ew.get_object()); + EXPECT_EQ(nullptr, ew.get_object()); EXPECT_EQ(nullptr, ew.to_exception_ptr()); EXPECT_EQ("", ew.class_name()); EXPECT_EQ("", ew.what()); -- 2.34.1