Refactors folly sync test cases
[folly.git] / folly / ExceptionWrapper.cpp
index d819c603e269ccfc812708931b2e605eb24177a8..79c67ea0dd3a0f945d7dc2a8c149b662f58e830c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2017 Facebook, Inc.
+ * Copyright 2016-present Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  */
 #include <folly/ExceptionWrapper.h>
 
-#include <exception>
 #include <iostream>
 
+#include <folly/Logging.h>
+
 namespace folly {
 
-[[noreturn]] void exception_wrapper::throwException() const {
-  if (throwfn_) {
-    throwfn_(*item_);
-  } else if (eptr_) {
-    std::rethrow_exception(eptr_);
+exception_wrapper::VTable const exception_wrapper::uninit_{
+    &noop_<void, exception_wrapper const*, exception_wrapper*>,
+    &noop_<void, exception_wrapper*, exception_wrapper*>,
+    &noop_<void, exception_wrapper*>,
+    &noop_<void, exception_wrapper const*>,
+    &uninit_type_,
+    &noop_<std::exception const*, exception_wrapper const*>,
+    &noop_<exception_wrapper, exception_wrapper const*>};
+
+exception_wrapper::VTable const exception_wrapper::ExceptionPtr::ops_{
+    copy_,
+    move_,
+    delete_,
+    throw_,
+    type_,
+    get_exception_,
+    get_exception_ptr_};
+
+exception_wrapper::VTable const exception_wrapper::SharedPtr::ops_{
+    copy_,
+    move_,
+    delete_,
+    throw_,
+    type_,
+    get_exception_,
+    get_exception_ptr_};
+
+namespace {
+std::exception const* get_std_exception_(std::exception_ptr eptr) noexcept {
+  try {
+    std::rethrow_exception(eptr);
+  } catch (const std::exception& ex) {
+    return &ex;
+  } catch (...) {
+    return nullptr;
   }
-  std::cerr
-      << "Cannot use `throwException` with an empty folly::exception_wrapper"
-      << std::endl;
-  std::terminate();
 }
+} // namespace
 
-fbstring exception_wrapper::class_name() const {
-  if (item_) {
-    auto& i = *item_;
-    return demangle(typeid(i));
-  } else if (eptr_ && eobj_) {
-    return demangle(typeid(*eobj_));
-  } else if (eptr_ && etype_) {
-    return demangle(*etype_);
-  } else {
-    return fbstring();
+exception_wrapper exception_wrapper::from_exception_ptr(
+    std::exception_ptr const& ptr) noexcept {
+  if (!ptr) {
+    return exception_wrapper();
+  }
+  try {
+    std::rethrow_exception(ptr);
+  } catch (std::exception& e) {
+    return exception_wrapper(std::current_exception(), e);
+  } catch (...) {
+    return exception_wrapper(std::current_exception());
   }
 }
 
-fbstring exception_wrapper::what() const {
-  if (item_) {
-    return exceptionStr(*item_);
-  } else if (eptr_ && eobj_) {
-    return class_name() + ": " + eobj_->what();
-  } else if (eptr_ && etype_) {
-    return class_name();
-  } else {
-    return class_name();
+exception_wrapper::exception_wrapper(std::exception_ptr ptr) noexcept
+    : exception_wrapper{} {
+  if (ptr) {
+    if (auto e = get_std_exception_(ptr)) {
+      LOG(DFATAL)
+          << "Performance error: Please construct exception_wrapper with a "
+             "reference to the std::exception along with the "
+             "std::exception_ptr.";
+      *this = exception_wrapper{std::move(ptr), *e};
+    } else {
+      Unknown uk;
+      *this = exception_wrapper{ptr, uk};
+    }
   }
 }
 
-fbstring exceptionStr(const exception_wrapper& ew) {
+[[noreturn]] void exception_wrapper::onNoExceptionError(
+    char const* const name) {
+  std::ios_base::Init ioinit_; // ensure std::cerr is alive
+  std::cerr << "Cannot use `" << name
+            << "` with an empty folly::exception_wrapper" << std::endl;
+  std::terminate();
+}
+
+fbstring exceptionStr(exception_wrapper const& ew) {
   return ew.what();
 }
 
-} // folly
+} // namespace folly