From: James Sedgwick Date: Fri, 19 Dec 2014 00:11:50 +0000 (-0800) Subject: onError callbacks X-Git-Tag: v0.22.0~84 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=ddb579a2abb24edf1b3a6b00ff8ae877bd67eddf;p=folly.git onError callbacks Summary: We've discussed these a bunch and here they are. I stole a bunch of Hannes' magic from https://www.facebook.com/groups/715931878455430/permalink/772854686096482/ to make this easier Test Plan: added lots of unit tests Reviewed By: hans@fb.com Subscribers: fugalh, folly-diffs@, hannesr FB internal diff: D1748418 Signature: t1:1748418:1418945606:e14c7d6a31245e222bc6a0d259d0e2b9ddd5a830 --- diff --git a/folly/wangle/futures/Future-inl.h b/folly/wangle/futures/Future-inl.h index 074571db..f2816b48 100644 --- a/folly/wangle/futures/Future-inl.h +++ b/folly/wangle/futures/Future-inl.h @@ -305,6 +305,77 @@ Future Future::then() { return then([] (Try&& t) {}); } +// onError where the callback returns T +template +template +typename std::enable_if< + !detail::Extract::ReturnsFuture::value, + Future>::type +Future::onError(F&& func) { + typedef typename detail::Extract::FirstArg Exn; + static_assert( + std::is_same::RawReturn, T>::value, + "Return type of onError callback must be T or Future"); + + Promise p; + auto f = p.getFuture(); + auto pm = folly::makeMoveWrapper(std::move(p)); + auto funcm = folly::makeMoveWrapper(std::move(func)); + setCallback_([pm, funcm](Try&& t) mutable { + try { + t.throwIfFailed(); + } catch (Exn& e) { + pm->fulfil([&]{ + return (*funcm)(e); + }); + return; + } catch (...) { + // fall through + } + pm->fulfilTry(std::move(t)); + }); + + return f; +} + +// onError where the callback returns Future +template +template +typename std::enable_if< + detail::Extract::ReturnsFuture::value, + Future>::type +Future::onError(F&& func) { + static_assert( + std::is_same::Return, Future>::value, + "Return type of onError callback must be T or Future"); + typedef typename detail::Extract::FirstArg Exn; + + Promise p; + auto f = p.getFuture(); + auto pm = folly::makeMoveWrapper(std::move(p)); + auto funcm = folly::makeMoveWrapper(std::move(func)); + setCallback_([pm, funcm](Try&& t) mutable { + try { + t.throwIfFailed(); + } catch (Exn& e) { + try { + auto f2 = (*funcm)(e); + f2.setCallback_([pm](Try&& t2) mutable { + pm->fulfilTry(std::move(t2)); + }); + } catch (...) { + pm->setException(std::current_exception()); + } + return; + } catch (...) { + // fall through + } + pm->fulfilTry(std::move(t)); + }); + + return f; +} + template typename std::add_lvalue_reference::type Future::value() { throwIfInvalid(); diff --git a/folly/wangle/futures/Future.h b/folly/wangle/futures/Future.h index cdea93df..15349e39 100644 --- a/folly/wangle/futures/Future.h +++ b/folly/wangle/futures/Future.h @@ -30,17 +30,62 @@ namespace folly { namespace wangle { namespace detail { - template struct Core; - template struct VariadicContext; - - template - struct AliasIfVoid { - typedef typename std::conditional< - std::is_same::value, - int, - T>::type type; - }; -} + +template struct Core; +template struct VariadicContext; + +template +struct AliasIfVoid { + typedef typename std::conditional< + std::is_same::value, + int, + T>::type type; +}; + + +template +struct IsFuture : std::integral_constant { + typedef T Inner; +}; + +template