Commit dc64cee6 authored by Hans Fugal's avatar Hans Fugal Committed by Sara Golemon

Future<T>::onTimeout(Duration, function<T()>, Timekeeper*=nullptr)

Summary:
(or func returns Future<T>)

Invoke and respond to a timeout with a callback, rather than using `within` and adding `onError` or `then` or something.

Test Plan: new tests

Reviewed By: davejwatson@fb.com

Subscribers: jsedgwick, yfeldblum, trunkagent, fugalh, exa, folly-diffs@

FB internal diff: D1763174

Tasks: 4548494

Signature: t1:1763174:1423074062:05cec1dfb1110b31b599033949ebe0ee70dd0552
parent eaed836c
...@@ -282,6 +282,14 @@ Future<T>::onError(F&& func) { ...@@ -282,6 +282,14 @@ Future<T>::onError(F&& func) {
return f; return f;
} }
template <class T>
template <class F>
Future<T> Future<T>::onTimeout(Duration dur, F&& func, Timekeeper* tk) {
auto funcw = folly::makeMoveWrapper(std::forward<F>(func));
return within(dur, tk)
.onError([funcw](TimedOut const&) { return (*funcw)(); });
}
template <class T> template <class T>
typename std::add_lvalue_reference<T>::type Future<T>::value() { typename std::add_lvalue_reference<T>::type Future<T>::value() {
throwIfInvalid(); throwIfInvalid();
......
...@@ -326,6 +326,22 @@ class Future { ...@@ -326,6 +326,22 @@ class Future {
Future<T>>::type Future<T>>::type
onError(F&& func); onError(F&& func);
/// Like onError, but for timeouts. example:
///
/// Future<int> f = makeFuture<int>(42)
/// .delayed(long_time)
/// .onTimeout(short_time,
/// []() -> int{ return -1; });
///
/// or perhaps
///
/// Future<int> f = makeFuture<int>(42)
/// .delayed(long_time)
/// .onTimeout(short_time,
/// []() { return makeFuture<int>(some_exception); });
template <class F>
Future<T> onTimeout(Duration, F&& func, Timekeeper* = nullptr);
/// This is not the method you're looking for. /// This is not the method you're looking for.
/// ///
/// This needs to be public because it's used by make* and when*, and it's /// This needs to be public because it's used by make* and when*, and it's
......
...@@ -126,3 +126,43 @@ TEST(Timekeeper, futureWithinException) { ...@@ -126,3 +126,43 @@ TEST(Timekeeper, futureWithinException) {
auto f = p.getFuture().within(awhile, std::runtime_error("expected")); auto f = p.getFuture().within(awhile, std::runtime_error("expected"));
EXPECT_THROW(f.get(), std::runtime_error); EXPECT_THROW(f.get(), std::runtime_error);
} }
TEST(Timekeeper, onTimeout) {
bool flag = false;
makeFuture(42).delayed(one_ms)
.onTimeout(Duration(0), [&]{ flag = true; return -1; })
.get();
EXPECT_TRUE(flag);
}
TEST(Timekeeper, onTimeoutReturnsFuture) {
bool flag = false;
makeFuture(42).delayed(one_ms)
.onTimeout(Duration(0), [&]{ flag = true; return makeFuture(-1); })
.get();
EXPECT_TRUE(flag);
}
TEST(Timekeeper, onTimeoutVoid) {
makeFuture().delayed(one_ms)
.onTimeout(Duration(0), [&]{
});
makeFuture().delayed(one_ms)
.onTimeout(Duration(0), [&]{
return makeFuture<void>(std::runtime_error("expected"));
});
// just testing compilation here
}
// TODO(5921764)
/*
TEST(Timekeeper, onTimeoutPropagates) {
bool flag = false;
EXPECT_THROW(
makeFuture(42).delayed(one_ms)
.onTimeout(Duration(0), [&]{ flag = true; })
.get(),
TimedOut);
EXPECT_TRUE(flag);
}
*/
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