Commit 790b68ac authored by Yedidya Feldblum's avatar Yedidya Feldblum Committed by Facebook Github Bot

RFC: Embed exception_wrapper directly into Try

Summary:
[Folly] RFC: Embed `exception_wrapper` directly into `Try`.

Rather than storing it elsewhere on the heap. With `exception_wrapper` at 24 bytes on x64, it may now be small enough. However, it will expand the size of `Try<T>` for `sizeof(T) <= 16`, giving `Try` a new minimum size of 32 bytes on x64 instead of 16.

Reviewed By: ericniebler

Differential Revision: D5051436

fbshipit-source-id: 10d59686d64382c88d54340c97567eafb3e2f682
parent 27249d44
...@@ -26,7 +26,7 @@ Try<T>::Try(Try<T>&& t) noexcept : contains_(t.contains_) { ...@@ -26,7 +26,7 @@ Try<T>::Try(Try<T>&& t) noexcept : contains_(t.contains_) {
if (contains_ == Contains::VALUE) { if (contains_ == Contains::VALUE) {
new (&value_)T(std::move(t.value_)); new (&value_)T(std::move(t.value_));
} else if (contains_ == Contains::EXCEPTION) { } else if (contains_ == Contains::EXCEPTION) {
new (&e_)std::unique_ptr<exception_wrapper>(std::move(t.e_)); new (&e_) exception_wrapper(std::move(t.e_));
} }
} }
...@@ -40,8 +40,7 @@ Try<T>::Try(typename std::enable_if<std::is_same<Unit, T2>::value, ...@@ -40,8 +40,7 @@ Try<T>::Try(typename std::enable_if<std::is_same<Unit, T2>::value,
new (&value_) T(); new (&value_) T();
} else if (t.hasException()) { } else if (t.hasException()) {
contains_ = Contains::EXCEPTION; contains_ = Contains::EXCEPTION;
new (&e_) std::unique_ptr<exception_wrapper>( new (&e_) exception_wrapper(t.exception());
std::make_unique<exception_wrapper>(t.exception()));
} }
} }
...@@ -56,7 +55,7 @@ Try<T>& Try<T>::operator=(Try<T>&& t) noexcept { ...@@ -56,7 +55,7 @@ Try<T>& Try<T>::operator=(Try<T>&& t) noexcept {
if (contains_ == Contains::VALUE) { if (contains_ == Contains::VALUE) {
new (&value_)T(std::move(t.value_)); new (&value_)T(std::move(t.value_));
} else if (contains_ == Contains::EXCEPTION) { } else if (contains_ == Contains::EXCEPTION) {
new (&e_)std::unique_ptr<exception_wrapper>(std::move(t.e_)); new (&e_) exception_wrapper(std::move(t.e_));
} }
return *this; return *this;
} }
...@@ -70,8 +69,7 @@ Try<T>::Try(const Try<T>& t) { ...@@ -70,8 +69,7 @@ Try<T>::Try(const Try<T>& t) {
if (contains_ == Contains::VALUE) { if (contains_ == Contains::VALUE) {
new (&value_)T(t.value_); new (&value_)T(t.value_);
} else if (contains_ == Contains::EXCEPTION) { } else if (contains_ == Contains::EXCEPTION) {
new (&e_)std::unique_ptr<exception_wrapper>(); new (&e_) exception_wrapper(t.e_);
e_ = std::make_unique<exception_wrapper>(*(t.e_));
} }
} }
...@@ -85,8 +83,7 @@ Try<T>& Try<T>::operator=(const Try<T>& t) { ...@@ -85,8 +83,7 @@ Try<T>& Try<T>::operator=(const Try<T>& t) {
if (contains_ == Contains::VALUE) { if (contains_ == Contains::VALUE) {
new (&value_)T(t.value_); new (&value_)T(t.value_);
} else if (contains_ == Contains::EXCEPTION) { } else if (contains_ == Contains::EXCEPTION) {
new (&e_)std::unique_ptr<exception_wrapper>(); new (&e_) exception_wrapper(t.e_);
e_ = std::make_unique<exception_wrapper>(*(t.e_));
} }
return *this; return *this;
} }
...@@ -96,7 +93,7 @@ Try<T>::~Try() { ...@@ -96,7 +93,7 @@ Try<T>::~Try() {
if (LIKELY(contains_ == Contains::VALUE)) { if (LIKELY(contains_ == Contains::VALUE)) {
value_.~T(); value_.~T();
} else if (UNLIKELY(contains_ == Contains::EXCEPTION)) { } else if (UNLIKELY(contains_ == Contains::EXCEPTION)) {
e_.~unique_ptr<exception_wrapper>(); e_.~exception_wrapper();
} }
} }
...@@ -122,7 +119,7 @@ template <class T> ...@@ -122,7 +119,7 @@ template <class T>
void Try<T>::throwIfFailed() const { void Try<T>::throwIfFailed() const {
if (contains_ != Contains::VALUE) { if (contains_ != Contains::VALUE) {
if (contains_ == Contains::EXCEPTION) { if (contains_ == Contains::EXCEPTION) {
e_->throw_exception(); e_.throw_exception();
} else { } else {
throw UsingUninitializedTry(); throw UsingUninitializedTry();
} }
...@@ -131,7 +128,7 @@ void Try<T>::throwIfFailed() const { ...@@ -131,7 +128,7 @@ void Try<T>::throwIfFailed() const {
void Try<void>::throwIfFailed() const { void Try<void>::throwIfFailed() const {
if (!hasValue_) { if (!hasValue_) {
e_->throw_exception(); e_.throw_exception();
} }
} }
......
...@@ -93,8 +93,7 @@ class Try { ...@@ -93,8 +93,7 @@ class Try {
* @param e The exception_wrapper * @param e The exception_wrapper
*/ */
explicit Try(exception_wrapper e) explicit Try(exception_wrapper e)
: contains_(Contains::EXCEPTION), : contains_(Contains::EXCEPTION), e_(std::move(e)) {}
e_(std::make_unique<exception_wrapper>(std::move(e))) {}
/* /*
* DEPRECATED * DEPRECATED
...@@ -107,10 +106,10 @@ class Try { ...@@ -107,10 +106,10 @@ class Try {
: contains_(Contains::EXCEPTION) { : contains_(Contains::EXCEPTION) {
try { try {
std::rethrow_exception(ep); std::rethrow_exception(ep);
} catch (const std::exception& e) { } catch (std::exception& e) {
e_ = std::make_unique<exception_wrapper>(std::current_exception(), e); e_ = exception_wrapper(std::current_exception(), e);
} catch (...) { } catch (...) {
e_ = std::make_unique<exception_wrapper>(std::current_exception()); e_ = exception_wrapper(std::current_exception());
} }
} }
...@@ -195,21 +194,21 @@ class Try { ...@@ -195,21 +194,21 @@ class Try {
*/ */
template <class Ex> template <class Ex>
bool hasException() const { bool hasException() const {
return hasException() && e_->is_compatible_with<Ex>(); return hasException() && e_.is_compatible_with<Ex>();
} }
exception_wrapper& exception() { exception_wrapper& exception() {
if (UNLIKELY(!hasException())) { if (UNLIKELY(!hasException())) {
throw TryException("exception(): Try does not contain an exception"); throw TryException("exception(): Try does not contain an exception");
} }
return *e_; return e_;
} }
const exception_wrapper& exception() const { const exception_wrapper& exception() const {
if (UNLIKELY(!hasException())) { if (UNLIKELY(!hasException())) {
throw TryException("exception(): Try does not contain an exception"); throw TryException("exception(): Try does not contain an exception");
} }
return *e_; return e_;
} }
/* /*
...@@ -220,11 +219,18 @@ class Try { ...@@ -220,11 +219,18 @@ class Try {
* @returns True if the Try held an Ex and func was executed, false otherwise * @returns True if the Try held an Ex and func was executed, false otherwise
*/ */
template <class Ex, class F> template <class Ex, class F>
bool withException(F func) {
if (!hasException()) {
return false;
}
return e_.with_exception(std::move(func));
}
template <class Ex, class F>
bool withException(F func) const { bool withException(F func) const {
if (!hasException()) { if (!hasException()) {
return false; return false;
} }
return e_->with_exception(std::move(func)); return e_.with_exception(std::move(func));
} }
template <bool isTry, typename R> template <bool isTry, typename R>
...@@ -241,7 +247,7 @@ class Try { ...@@ -241,7 +247,7 @@ class Try {
Contains contains_; Contains contains_;
union { union {
T value_; T value_;
std::unique_ptr<exception_wrapper> e_; exception_wrapper e_;
}; };
}; };
...@@ -265,9 +271,7 @@ class Try<void> { ...@@ -265,9 +271,7 @@ class Try<void> {
* *
* @param e The exception_wrapper * @param e The exception_wrapper
*/ */
explicit Try(exception_wrapper e) explicit Try(exception_wrapper e) : hasValue_(false), e_(std::move(e)) {}
: hasValue_(false),
e_(std::make_unique<exception_wrapper>(std::move(e))) {}
/* /*
* DEPRECATED * DEPRECATED
...@@ -280,18 +284,16 @@ class Try<void> { ...@@ -280,18 +284,16 @@ class Try<void> {
try { try {
std::rethrow_exception(ep); std::rethrow_exception(ep);
} catch (const std::exception& e) { } catch (const std::exception& e) {
e_ = std::make_unique<exception_wrapper>(std::current_exception(), e); e_ = exception_wrapper(std::current_exception(), e);
} catch (...) { } catch (...) {
e_ = std::make_unique<exception_wrapper>(std::current_exception()); e_ = exception_wrapper(std::current_exception());
} }
} }
// Copy assigner // Copy assigner
Try& operator=(const Try<void>& t) { Try& operator=(const Try<void>& t) {
hasValue_ = t.hasValue_; hasValue_ = t.hasValue_;
if (t.e_) { e_ = t.e_;
e_ = std::make_unique<exception_wrapper>(*t.e_);
}
return *this; return *this;
} }
// Copy constructor // Copy constructor
...@@ -315,7 +317,7 @@ class Try<void> { ...@@ -315,7 +317,7 @@ class Try<void> {
// @returns True if the Try contains an exception of type Ex, false otherwise // @returns True if the Try contains an exception of type Ex, false otherwise
template <class Ex> template <class Ex>
bool hasException() const { bool hasException() const {
return hasException() && e_->is_compatible_with<Ex>(); return hasException() && e_.is_compatible_with<Ex>();
} }
/* /*
...@@ -327,14 +329,14 @@ class Try<void> { ...@@ -327,14 +329,14 @@ class Try<void> {
if (UNLIKELY(!hasException())) { if (UNLIKELY(!hasException())) {
throw TryException("exception(): Try does not contain an exception"); throw TryException("exception(): Try does not contain an exception");
} }
return *e_; return e_;
} }
const exception_wrapper& exception() const { const exception_wrapper& exception() const {
if (UNLIKELY(!hasException())) { if (UNLIKELY(!hasException())) {
throw TryException("exception(): Try does not contain an exception"); throw TryException("exception(): Try does not contain an exception");
} }
return *e_; return e_;
} }
/* /*
...@@ -345,11 +347,18 @@ class Try<void> { ...@@ -345,11 +347,18 @@ class Try<void> {
* @returns True if the Try held an Ex and func was executed, false otherwise * @returns True if the Try held an Ex and func was executed, false otherwise
*/ */
template <class Ex, class F> template <class Ex, class F>
bool withException(F func) {
if (!hasException()) {
return false;
}
return e_.with_exception(std::move(func));
}
template <class Ex, class F>
bool withException(F func) const { bool withException(F func) const {
if (!hasException()) { if (!hasException()) {
return false; return false;
} }
return e_->with_exception(std::move(func)); return e_.with_exception(std::move(func));
} }
template <bool, typename R> template <bool, typename R>
...@@ -359,7 +368,7 @@ class Try<void> { ...@@ -359,7 +368,7 @@ class Try<void> {
private: private:
bool hasValue_; bool hasValue_;
std::unique_ptr<exception_wrapper> e_{nullptr}; exception_wrapper e_;
}; };
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment