Optimize ZSTDCodec::doUncompress()
[folly.git] / folly / ExceptionWrapper.h
index a6023267a4716f8d4889b814e04b9a689b562646..bd5bc11972c5555ace1a269d767e8e1459c0a470 100644 (file)
@@ -25,6 +25,7 @@
 
 #include <folly/ExceptionString.h>
 #include <folly/FBString.h>
+#include <folly/Traits.h>
 
 namespace folly {
 
@@ -107,20 +108,19 @@ namespace folly {
  */
 class exception_wrapper {
  private:
-  template <typename Ex>
-  struct optimize;
+  template <typename T>
+  using is_exception_ = std::is_base_of<std::exception, T>;
 
  public:
   exception_wrapper() = default;
 
-  // Implicitly construct an exception_wrapper from a qualifying exception.
-  // See the optimize struct for details.
-  template <typename Ex, typename =
-    typename std::enable_if<optimize<typename std::decay<Ex>::type>::value>
-    ::type>
+  template <
+      typename Ex,
+      typename DEx = _t<std::decay<Ex>>,
+      typename = _t<std::enable_if<is_exception_<DEx>::value>>,
+      typename = decltype(DEx(std::forward<Ex>(std::declval<Ex&&>())))>
   /* implicit */ exception_wrapper(Ex&& exn) {
-    typedef typename std::decay<Ex>::type DEx;
-    assign_sptr(std::make_shared<DEx>(std::forward<Ex>(exn)));
+    assign_sptr<DEx>(std::forward<Ex>(exn));
   }
 
   // The following two constructors are meant to emulate the behavior of
@@ -195,13 +195,13 @@ class exception_wrapper {
 
   template <class F>
   bool with_exception(F&& f) {
-    using arg_type = typename functor_traits<F>::arg_type_decayed;
+    using arg_type = _t<std::decay<typename functor_traits<F>::arg_type>>;
     return with_exception<arg_type>(std::forward<F>(f));
   }
 
   template <class F>
   bool with_exception(F&& f) const {
-    using arg_type = typename functor_traits<F>::arg_type_decayed;
+    using arg_type = _t<std::decay<typename functor_traits<F>::arg_type>>;
     return with_exception<arg_type>(std::forward<F>(f));
   }
 
@@ -210,16 +210,16 @@ class exception_wrapper {
   // will otherwise return false.
   template <class Ex, class F>
   bool with_exception(F f) {
-    return with_exception1<typename std::decay<Ex>::type>(f, this);
+    return with_exception1<_t<std::decay<Ex>>>(std::forward<F>(f), this);
   }
 
   // Const overload
   template <class Ex, class F>
   bool with_exception(F f) const {
-    return with_exception1<typename std::decay<Ex>::type>(f, this);
+    return with_exception1<_t<std::decay<Ex>>>(std::forward<F>(f), this);
   }
 
-  std::exception_ptr getExceptionPtr() const {
+  std::exception_ptr to_exception_ptr() const {
     if (eptr_) {
       return eptr_;
     }
@@ -235,25 +235,26 @@ class exception_wrapper {
   }
 
  private:
-  template <typename Ex>
-  struct optimize {
-    static const bool value =
-      std::is_base_of<std::exception, Ex>::value &&
-      std::is_copy_assignable<Ex>::value &&
-      !std::is_abstract<Ex>::value;
-  };
+  template <typename Ex, typename... Args>
+  void assign_sptr(Args&&... args) {
+    this->item_ = std::make_shared<Ex>(std::forward<Args>(args)...);
+    this->throwfn_ = Thrower<Ex>::doThrow;
+  }
 
   template <typename Ex>
-  void assign_sptr(std::shared_ptr<Ex> sptr) {
-    this->item_ = std::move(sptr);
-    this->throwfn_ = Thrower<Ex>::doThrow;
+  _t<std::enable_if<is_exception_<Ex>::value>> assign_eptr(
+      std::exception_ptr eptr,
+      Ex& e) {
+    this->eptr_ = eptr;
+    this->eobj_ = &const_cast<_t<std::remove_const<Ex>>&>(e);
   }
 
   template <typename Ex>
-  void assign_eptr(std::exception_ptr eptr, Ex& e) {
+  _t<std::enable_if<!is_exception_<Ex>::value>> assign_eptr(
+      std::exception_ptr eptr,
+      Ex& e) {
     this->eptr_ = eptr;
-    this->estr_ = exceptionStr(e).toStdString();
-    this->ename_ = demangle(typeid(e)).toStdString();
+    this->etype_ = &typeid(e);
   }
 
   void assign_eptr(std::exception_ptr eptr) {
@@ -270,8 +271,8 @@ class exception_wrapper {
   // 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_;
+  std::exception* eobj_{nullptr};
+  const std::type_info* etype_{nullptr};
 
   template <class T, class... Args>
   friend exception_wrapper make_exception_wrapper(Args&&... args);
@@ -285,10 +286,8 @@ class exception_wrapper {
     struct impl<R(C::*)(A)> { using arg_type = A; };
     template <typename C, typename R, typename A>
     struct impl<R(C::*)(A) const> { using arg_type = A; };
-    using functor_decayed = typename std::decay<F>::type;
-    using functor_op = decltype(&functor_decayed::operator());
+    using functor_op = decltype(&_t<std::decay<F>>::operator());
     using arg_type = typename impl<functor_op>::arg_type;
-    using arg_type_decayed = typename std::decay<arg_type>::type;
   };
 
   template <class T>
@@ -299,19 +298,13 @@ class exception_wrapper {
     }
   };
 
-  template <typename T>
-  using is_exception_ = std::is_base_of<std::exception, T>;
-
-  template <bool V, typename T, typename F>
-  using conditional_t_ = typename std::conditional<V, T, F>::type;
-
   template <typename T, typename F>
-  static typename std::enable_if<is_exception_<T>::value, T*>::type
+  static _t<std::enable_if<is_exception_<T>::value, T*>>
   try_dynamic_cast_exception(F* from) {
     return dynamic_cast<T*>(from);
   }
   template <typename T, typename F>
-  static typename std::enable_if<!is_exception_<T>::value, T*>::type
+  static _t<std::enable_if<!is_exception_<T>::value, T*>>
   try_dynamic_cast_exception(F*) {
     return nullptr;
   }
@@ -321,9 +314,12 @@ class exception_wrapper {
   // instantiation which works with F.
   template <class Ex, class F, class T>
   static bool with_exception1(F f, T* that) {
-    using CEx = conditional_t_<std::is_const<T>::value, const Ex, Ex>;
-    if (is_exception_<Ex>::value && that->item_) {
-      if (auto ex = try_dynamic_cast_exception<CEx>(that->item_.get())) {
+    using CEx = _t<std::conditional<std::is_const<T>::value, const Ex, Ex>>;
+    if (is_exception_<Ex>::value &&
+        (that->item_ || (that->eptr_ && that->eobj_))) {
+      auto raw =
+          that->item_ ? that->item_.get() : that->eptr_ ? that->eobj_ : nullptr;
+      if (auto ex = try_dynamic_cast_exception<CEx>(raw)) {
         f(*ex);
         return true;
       }
@@ -341,10 +337,10 @@ class exception_wrapper {
   }
 };
 
-template <class T, class... Args>
+template <class Ex, class... Args>
 exception_wrapper make_exception_wrapper(Args&&... args) {
   exception_wrapper ew;
-  ew.assign_sptr(std::make_shared<T>(std::forward<Args>(args)...));
+  ew.assign_sptr<Ex>(std::forward<Args>(args)...);
   return ew;
 }
 
@@ -393,19 +389,18 @@ fbstring exceptionStr(const exception_wrapper& ew);
 
 namespace try_and_catch_detail {
 
-template <bool V, typename T = void>
-using enable_if_t_ = typename std::enable_if<V, T>::type;
-
 template <typename... Args>
 using is_wrap_ctor = std::is_constructible<exception_wrapper, Args...>;
 
 template <typename Ex>
-inline enable_if_t_<!is_wrap_ctor<Ex&>::value, exception_wrapper> make(Ex& ex) {
+inline _t<std::enable_if<!is_wrap_ctor<Ex&>::value, exception_wrapper>> make(
+    Ex& ex) {
   return exception_wrapper(std::current_exception(), ex);
 }
 
 template <typename Ex>
-inline enable_if_t_<is_wrap_ctor<Ex&>::value, exception_wrapper> make(Ex& ex) {
+inline _t<std::enable_if<is_wrap_ctor<Ex&>::value, exception_wrapper>> make(
+    Ex& ex) {
   return typeid(Ex&) == typeid(ex)
       ? exception_wrapper(ex)
       : exception_wrapper(std::current_exception(), ex);