Let make_exception_wrapper construct on-heap objects in-place
authorYedidya Feldblum <yfeldblum@fb.com>
Mon, 26 Jun 2017 20:22:19 +0000 (13:22 -0700)
committerFacebook Github Bot <facebook-github-bot@users.noreply.github.com>
Mon, 26 Jun 2017 20:28:02 +0000 (13:28 -0700)
Summary:
[Folly] Let `make_exception_wrapper` construct on-heap objects in-place.

Currently, it constructs on-heap objects on the stack and then move-constructs them into on-heap storage.

Reviewed By: ericniebler

Differential Revision: D5315104

fbshipit-source-id: cc0493e7d98aacadd342eb56601028ced4a19bb3

folly/ExceptionWrapper-inl.h
folly/ExceptionWrapper.h

index 2845c2e..c1e8378 100644 (file)
@@ -69,9 +69,9 @@ inline std::type_info const* exception_wrapper::uninit_type_(
   return &typeid(void);
 }
 
-template <class Ex, class DEx>
-inline exception_wrapper::Buffer::Buffer(in_place_t, Ex&& ex) {
-  ::new (static_cast<void*>(&buff_)) DEx(std::forward<Ex>(ex));
+template <class Ex, typename... As>
+inline exception_wrapper::Buffer::Buffer(in_place_type_t<Ex>, As&&... as_) {
+  ::new (static_cast<void*>(&buff_)) Ex(std::forward<As>(as_)...);
 }
 
 template <class Ex>
@@ -280,14 +280,15 @@ inline exception_wrapper exception_wrapper::SharedPtr::get_exception_ptr_(
   return that->sptr_.ptr_->get_exception_ptr_();
 }
 
-template <class Ex, class DEx>
-inline exception_wrapper::exception_wrapper(Ex&& ex, OnHeapTag)
-    : sptr_{std::make_shared<SharedPtr::Impl<DEx>>(std::forward<Ex>(ex))},
+template <class Ex, typename... As>
+inline exception_wrapper::exception_wrapper(OnHeapTag, in_place_type_t<Ex>, As&&... as)
+    : sptr_{std::make_shared<SharedPtr::Impl<Ex>>(std::forward<As>(as)...)},
       vptr_(&SharedPtr::ops_) {}
 
-template <class Ex, class DEx>
-inline exception_wrapper::exception_wrapper(Ex&& ex, InSituTag)
-    : buff_{in_place, std::forward<Ex>(ex)}, vptr_(&InPlace<DEx>::ops_) {}
+template <class Ex, typename... As>
+inline exception_wrapper::exception_wrapper(InSituTag, in_place_type_t<Ex>, As&&... as)
+    : buff_{in_place<Ex>, std::forward<As>(as)...},
+      vptr_(&InPlace<Ex>::ops_) {}
 
 inline exception_wrapper::exception_wrapper(exception_wrapper&& that) noexcept
     : exception_wrapper{} {
@@ -345,8 +346,9 @@ template <
             exception_wrapper::IsRegularExceptionType<Ex_>>::value)>
 inline exception_wrapper::exception_wrapper(Ex&& ex)
     : exception_wrapper{
-        exception_wrapper_detail::dont_slice(std::forward<Ex>(ex)),
-        PlacementOf<Ex_>{}} {
+        PlacementOf<Ex_>{},
+        in_place<Ex_>,
+        exception_wrapper_detail::dont_slice(std::forward<Ex>(ex))} {
 }
 
 template <
@@ -356,8 +358,21 @@ template <
         exception_wrapper::IsRegularExceptionType<Ex_>::value)>
 inline exception_wrapper::exception_wrapper(in_place_t, Ex&& ex)
     : exception_wrapper{
-        exception_wrapper_detail::dont_slice(std::forward<Ex>(ex)),
-        PlacementOf<Ex_>{}} {
+        PlacementOf<Ex_>{},
+        in_place<Ex_>,
+        exception_wrapper_detail::dont_slice(std::forward<Ex>(ex))} {
+}
+
+template <
+    class Ex,
+    typename... As,
+    FOLLY_REQUIRES_DEF(
+        exception_wrapper::IsRegularExceptionType<Ex>::value)>
+inline exception_wrapper::exception_wrapper(in_place_type_t<Ex>, As&&... as)
+    : exception_wrapper{
+        PlacementOf<Ex>{},
+        in_place<Ex>,
+        std::forward<As>(as)...} {
 }
 
 inline void exception_wrapper::swap(exception_wrapper& that) noexcept {
index 449080d..958a3d3 100644 (file)
@@ -226,8 +226,8 @@ class exception_wrapper final {
 
     Buffer() : buff_{} {}
 
-    template <class Ex, class DEx = _t<std::decay<Ex>>>
-    Buffer(in_place_t, Ex&& ex);
+    template <class Ex, typename... As>
+    Buffer(in_place_type_t<Ex>, As&&... as_);
     template <class Ex>
     Ex& as() noexcept;
     template <class Ex>
@@ -309,10 +309,10 @@ class exception_wrapper final {
     struct Impl final : public Base {
       Ex ex_;
       Impl() = default;
-      explicit Impl(Ex const& ex) : Base{typeid(ex)}, ex_(ex) {}
-      explicit Impl(Ex&& ex)
-          : Base{typeid(ex)},
-            ex_(std::move(ex)){}[[noreturn]] void throw_() const override;
+      template <typename... As>
+      explicit Impl(As&&... as)
+          : Base{typeid(Ex)}, ex_(std::forward<As>(as)...) {}
+      [[noreturn]] void throw_() const override;
       std::exception const* get_exception_() const noexcept override;
       exception_wrapper get_exception_ptr_() const noexcept override;
     };
@@ -335,11 +335,11 @@ class exception_wrapper final {
   };
   VTable const* vptr_{&uninit_};
 
-  template <class Ex, class DEx = _t<std::decay<Ex>>>
-  exception_wrapper(Ex&& ex, OnHeapTag);
+  template <class Ex, typename... As>
+  exception_wrapper(OnHeapTag, in_place_type_t<Ex>, As&&... as);
 
-  template <class Ex, class DEx = _t<std::decay<Ex>>>
-  exception_wrapper(Ex&& ex, InSituTag);
+  template <class Ex, typename... As>
+  exception_wrapper(InSituTag, in_place_type_t<Ex>, As&&... as);
 
   template <class T>
   struct IsRegularExceptionType
@@ -434,6 +434,12 @@ class exception_wrapper final {
       FOLLY_REQUIRES(IsRegularExceptionType<Ex_>::value)>
   exception_wrapper(in_place_t, Ex&& ex);
 
+  template <
+      class Ex,
+      typename... As,
+      FOLLY_REQUIRES(IsRegularExceptionType<Ex>::value)>
+  exception_wrapper(in_place_type_t<Ex>, As&&... as);
+
   //! Swaps the value of `*this` with the value of `that`
   void swap(exception_wrapper& that) noexcept;
 
@@ -598,7 +604,7 @@ constexpr exception_wrapper::VTable exception_wrapper::InPlace<Ex>::ops_;
  */
 template <class Ex, typename... As>
 exception_wrapper make_exception_wrapper(As&&... as) {
-  return exception_wrapper{Ex{std::forward<As>(as)...}};
+  return exception_wrapper{in_place<Ex>, std::forward<As>(as)...};
 }
 
 /**