if (f.isReady()) return;
folly::fibers::Baton baton;
- f.setCallback_([&](const Try<T>& t) { baton.post(); });
+ f = f.then([&](Try<T> t) {
+ baton.post();
+ return makeFuture(std::move(t));
+ });
baton.wait();
+
+ // There's a race here between the return here and the actual finishing of
+ // the future. f is completed, but the setup may not have finished on done
+ // after the baton has posted.
+ while (!f.isReady()) {
+ std::this_thread::yield();
+ }
}
template <class T>
if (f.isReady()) return;
auto baton = std::make_shared<folly::fibers::Baton>();
- f.setCallback_([baton](const Try<T>& t) {
+ f = f.then([baton](Try<T> t) {
baton->post();
+ return makeFuture(std::move(t));
});
- baton->timed_wait(dur);
+
+ // Let's preserve the invariant that if we did not timeout (timed_wait returns
+ // true), then the returned Future is complete when it is returned to the
+ // caller. We need to wait out the race for that Future to complete.
+ if (baton->timed_wait(dur)) {
+ while (!f.isReady()) {
+ std::this_thread::yield();
+ }
+ }
}
template <class T>