| 1622 | template <typename T> |
| 1623 | template <typename F> |
| 1624 | Future<T> Future<T>::recover(F&& f) const |
| 1625 | { |
| 1626 | std::shared_ptr<Promise<T>> promise(new Promise<T>()); |
| 1627 | |
| 1628 | const Future<T> future = *this; |
| 1629 | |
| 1630 | typedef decltype(std::move(f)(future)) R; |
| 1631 | |
| 1632 | std::shared_ptr<lambda::CallableOnce<R(const Future<T>&)>> callable( |
| 1633 | new lambda::CallableOnce<R(const Future<T>&)>(std::move(f))); |
| 1634 | |
| 1635 | onAny([=]() { |
| 1636 | if (future.isDiscarded() || future.isFailed()) { |
| 1637 | // We reset `discard` so that if a future gets returned from |
| 1638 | // `f(future)` we won't immediately discard it! We still want to |
| 1639 | // let the future get discarded later, however, hence if it gets |
| 1640 | // set again in the future it'll propagate to the returned |
| 1641 | // future. |
| 1642 | synchronized (promise->f.data->lock) { |
| 1643 | promise->f.data->discard = false; |
| 1644 | } |
| 1645 | |
| 1646 | promise->set(std::move(*callable)(future)); |
| 1647 | } else { |
| 1648 | promise->associate(future); |
| 1649 | } |
| 1650 | }); |
| 1651 | |
| 1652 | onAbandoned([=]() { |
| 1653 | // See comment above for why we reset `discard` here. |
| 1654 | synchronized (promise->f.data->lock) { |
| 1655 | promise->f.data->discard = false; |
| 1656 | } |
| 1657 | promise->set(std::move(*callable)(future)); |
| 1658 | }); |
| 1659 | |
| 1660 | // Propagate discarding up the chain. To avoid cyclic dependencies, |
| 1661 | // we keep a weak future in the callback. |
| 1662 | promise->future().onDiscard( |
| 1663 | lambda::bind(&internal::discard<T>, WeakFuture<T>(*this))); |
| 1664 | |
| 1665 | return promise->future(); |
| 1666 | } |
| 1667 | |
| 1668 | |
| 1669 | template <typename T> |