mirror of
https://github.com/scylladb/scylladb.git
synced 2026-04-22 17:40:34 +00:00
future: add then_wrapped()
Unlike future::then(), which unwraps the value, then_wrapped() keeps it wrapped in a future<>, so if it is exceptional, it can still be accessed. This is similar to the proposed std::future::then(), so we should later rename it to match (and rename the existing future::then() to future::next().
This commit is contained in:
@@ -257,6 +257,7 @@ template <typename... T> struct is_future : std::false_type {};
|
||||
template <typename... T> struct is_future<future<T...>> : std::true_type {};
|
||||
|
||||
struct ready_future_marker {};
|
||||
struct ready_future_from_tuple_marker {};
|
||||
struct exception_future_marker {};
|
||||
|
||||
template <typename... T>
|
||||
@@ -273,6 +274,10 @@ private:
|
||||
future(ready_future_marker, A&&... a) : _promise(nullptr) {
|
||||
_local_state.set(std::forward<A>(a)...);
|
||||
}
|
||||
template <typename... A>
|
||||
future(ready_future_from_tuple_marker, std::tuple<A...>&& data) : _promise(nullptr) {
|
||||
_local_state.set(std::move(data));
|
||||
}
|
||||
future(exception_future_marker, std::exception_ptr ex) noexcept : _promise(nullptr) {
|
||||
_local_state.set_exception(std::move(ex));
|
||||
}
|
||||
@@ -386,6 +391,34 @@ public:
|
||||
return next_fut;
|
||||
}
|
||||
|
||||
template <typename Func>
|
||||
std::result_of_t<Func(future<T...>)>
|
||||
then_wrapped(Func&& func) && noexcept {
|
||||
using P = typename std::result_of_t<Func(future<T...>)>::promise_type;
|
||||
if (state()->available()) {
|
||||
try {
|
||||
return func(std::move(*this));
|
||||
} catch (...) {
|
||||
P pr;
|
||||
pr.set_exception(std::current_exception());
|
||||
return pr.get_future();
|
||||
}
|
||||
}
|
||||
P pr;
|
||||
auto next_fut = pr.get_future();
|
||||
_promise->schedule([func = std::forward<Func>(func), pr = std::move(pr)] (auto& state) mutable {
|
||||
try {
|
||||
auto next_fut = func(future(ready_future_from_tuple_marker(), state.get()));
|
||||
next_fut.forward_to(std::move(pr));
|
||||
} catch (...) {
|
||||
pr.set_exception(std::current_exception());
|
||||
}
|
||||
});
|
||||
_promise->_future = nullptr;
|
||||
_promise = nullptr;
|
||||
return next_fut;
|
||||
}
|
||||
|
||||
template <typename Func>
|
||||
future<> rescue(Func&& func) noexcept {
|
||||
if (state()->available()) {
|
||||
|
||||
Reference in New Issue
Block a user