| 1690 | |
| 1691 | template <typename T> |
| 1692 | Future<T> Future<T>::after( |
| 1693 | const Duration& duration, |
| 1694 | lambda::CallableOnce<Future<T>(const Future<T>&)> f) const |
| 1695 | { |
| 1696 | // TODO(benh): Using a Latch here but Once might be cleaner. |
| 1697 | // Unfortunately, Once depends on Future so we can't easily use it |
| 1698 | // from here. |
| 1699 | std::shared_ptr<Latch> latch(new Latch()); |
| 1700 | std::shared_ptr<Promise<T>> promise(new Promise<T>()); |
| 1701 | |
| 1702 | // We need to control the lifetime of the timer we create below so |
| 1703 | // that we can force the timer to get deallocated after it |
| 1704 | // expires. The reason we want to force the timer to get deallocated |
| 1705 | // after it expires is because the timer's lambda has a copy of |
| 1706 | // `this` (i.e., a Future) and it's stored in the `onAny` callbacks |
| 1707 | // of `this` thus creating a circular reference. By storing a |
| 1708 | // `shared_ptr<Option<Timer>>` we're able to set the option to none |
| 1709 | // after the timer expires which will deallocate our copy of the |
| 1710 | // timer and leave the `Option<Timer>` stored in the lambda of the |
| 1711 | // `onAny` callback as none. Note that this is safe because the |
| 1712 | // `Latch` makes sure that only one of the callbacks will manipulate |
| 1713 | // the `shared_ptr<Option<Timer>>` so there isn't any concurrency |
| 1714 | // issues we have to worry about. |
| 1715 | std::shared_ptr<Option<Timer>> timer(new Option<Timer>()); |
| 1716 | |
| 1717 | typedef lambda::CallableOnce<Future<T>(const Future<T>&)> F; |
| 1718 | std::shared_ptr<F> callable(new F(std::move(f))); |
| 1719 | |
| 1720 | // Set up a timer to invoke the callback if this future has not |
| 1721 | // completed. Note that we do not pass a weak reference for this |
| 1722 | // future as we don't want the future to get cleaned up and then |
| 1723 | // have the timer expire because then we wouldn't have a valid |
| 1724 | // future that we could pass to `f`! The reference to `this` that is |
| 1725 | // captured in the timer will get removed by setting the |
| 1726 | // `Option<Timer>` to none (see comment above) either if the timer |
| 1727 | // expires or if `this` completes and we cancel the timer (see |
| 1728 | // `internal::expired` and `internal::after` callbacks for where we |
| 1729 | // force the deallocation of our copy of the timer). |
| 1730 | *timer = Clock::timer( |
| 1731 | duration, |
| 1732 | lambda::bind(&internal::expired<T>, callable, latch, promise, timer, |
| 1733 | *this)); |
| 1734 | |
| 1735 | onAny(lambda::bind(&internal::after<T>, latch, promise, timer, lambda::_1)); |
| 1736 | |
| 1737 | onAbandoned([=]() { |
| 1738 | promise->future().abandon(); |
| 1739 | }); |
| 1740 | |
| 1741 | // Propagate discarding up the chain. To avoid cyclic dependencies, |
| 1742 | // we keep a weak future in the callback. |
| 1743 | promise->future().onDiscard( |
| 1744 | lambda::bind(&internal::discard<T>, WeakFuture<T>(*this))); |
| 1745 | |
| 1746 | return promise->future(); |
| 1747 | } |
| 1748 | |
| 1749 | |