X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=folly%2FExceptionWrapper.h;h=22857a0b9b543259f504e52dc9283b9bf023db52;hb=5022d5469d551c2a62d367792da9453392c464fa;hp=8284ec1fa538ecc20be819bdf7b58bfb818b6987;hpb=275ca94d04e44f28cfa411668eb1c1dd8db90b80;p=folly.git diff --git a/folly/ExceptionWrapper.h b/folly/ExceptionWrapper.h index 8284ec1f..22857a0b 100644 --- a/folly/ExceptionWrapper.h +++ b/folly/ExceptionWrapper.h @@ -1,5 +1,5 @@ /* - * Copyright 2015 Facebook, Inc. + * Copyright 2016 Facebook, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,8 +14,7 @@ * limitations under the License. */ -#ifndef FOLLY_EXCEPTIONWRAPPER_H -#define FOLLY_EXCEPTIONWRAPPER_H +#pragma once #include #include @@ -88,16 +87,15 @@ namespace folly { * * // Thread2: Exceptions are bad! * void processResult() { - * auto ep = globalExceptionWrapper.get(); - * if (!ep.with_exception([&]( - * FacePlantException& faceplant) { - * LOG(ERROR) << "FACEPLANT"; - * })) { - * ep.with_exception([&]( - * FailWhaleException& failwhale) { + * globalExceptionWrapper.with_exception( + * [&](FacePlantException& faceplant) { + * LOG(ERROR) << "FACEPLANT"; + * }) || + * globalExceptionWrapper.with_exception( + * [&](FailWhaleException& failwhale) { * LOG(ERROR) << "FAILWHALE!"; - * }); - * } + * }) || + * LOG(FATAL) << "Unrecognized exception"; * } * */ @@ -112,10 +110,12 @@ class exception_wrapper { // Implicitly construct an exception_wrapper from a qualifying exception. // See the optimize struct for details. template ::value>::type> + typename std::enable_if::type>::value> + ::type> /* implicit */ exception_wrapper(Ex&& exn) { - item_ = std::make_shared(std::forward(exn)); - throwfn_ = folly::detail::Thrower::doThrow; + typedef typename std::decay::type DEx; + item_ = std::make_shared(std::forward(exn)); + throwfn_ = folly::detail::Thrower::doThrow; } // The following two constructors are meant to emulate the behavior of @@ -212,8 +212,8 @@ class exception_wrapper { } else if (eptr_) { try { std::rethrow_exception(eptr_); - } catch (std::exception& e) { - return dynamic_cast(&e); + } catch (typename std::decay::type&) { + return true; } catch (...) { // fall through } @@ -221,6 +221,18 @@ class exception_wrapper { return false; } + template + bool with_exception(F&& f) { + using arg_type = typename functor_traits::arg_type_decayed; + return with_exception(std::forward(f)); + } + + template + bool with_exception(F&& f) const { + using arg_type = typename functor_traits::arg_type_decayed; + return with_exception(std::forward(f)); + } + // If this exception wrapper wraps an exception of type Ex, with_exception // will call f with the wrapped exception as an argument and return true, and // will otherwise return false. @@ -308,6 +320,20 @@ protected: friend exception_wrapper make_exception_wrapper(Args&&... args); private: + template + struct functor_traits { + template + struct impl; + template + struct impl { using arg_type = A; }; + template + struct impl { using arg_type = A; }; + using functor_decayed = typename std::decay::type; + using functor_op = decltype(&functor_decayed::operator()); + using arg_type = typename impl::arg_type; + using arg_type_decayed = typename std::decay::type; + }; + // What makes this useful is that T can be exception_wrapper* or // const exception_wrapper*, and the compiler will use the // instantiation which works with F. @@ -321,11 +347,9 @@ private: } else if (that->eptr_) { try { std::rethrow_exception(that->eptr_); - } catch (std::exception& e) { - if (auto ex = dynamic_cast(&e)) { - f(*ex); - return true; - } + } catch (Ex& e) { + f(e); + return true; } catch (...) { // fall through } @@ -342,6 +366,11 @@ exception_wrapper make_exception_wrapper(Args&&... args) { return ew; } +// For consistency with exceptionStr() functions in String.h +inline fbstring exceptionStr(const exception_wrapper& ew) { + return ew.what(); +} + /* * try_and_catch is a simple replacement for try {} catch(){} that allows you to * specify which derived exceptions you would like to catch and store in an @@ -407,7 +436,7 @@ class try_and_catch : template typename std::enable_if::value>::type - assign_exception(Ex& e, std::exception_ptr eptr) { + assign_exception(Ex& e, std::exception_ptr /*eptr*/) { this->item_ = std::make_shared(e); this->throwfn_ = folly::detail::Thrower::doThrow; } @@ -429,7 +458,7 @@ class try_and_catch : template<> class try_and_catch<> : public exception_wrapper { public: - try_and_catch() {} + try_and_catch() = default; protected: template @@ -438,4 +467,3 @@ class try_and_catch<> : public exception_wrapper { } }; } -#endif