#pragma once
#include "detail.h"
+#include <folly/LifoSem.h>
namespace folly { namespace wangle {
return ctx->p.getFuture();
}
+template <typename F>
+typename F::value_type waitWithSemaphore(F&& f) {
+ LifoSem sem;
+ Try<typename F::value_type> done;
+ f.then([&](Try<typename F::value_type> &&t) {
+ done = std::move(t);
+ sem.post();
+ });
+ sem.wait();
+ return done.value();
+}
+
}}
// I haven't included a Future<T&> specialization because I don't forsee us
Try<typename std::iterator_traits<InputIterator>::value_type::value_type>>>>
whenN(InputIterator first, InputIterator last, size_t n);
+/** Wait for the given future to complete on a semaphore. Returns the result of
+ * the given future.
+ *
+ * NB if the promise for the future would be fulfilled in the same thread that
+ * you call this, it will deadlock.
+ */
+template <class F>
+typename F::value_type waitWithSemaphore(F&& f);
+
}} // folly::wangle
#include "Future-inl.h"
*/
#include <algorithm>
+#include <atomic>
#include <folly/small_vector.h>
#include <gtest/gtest.h>
#include <memory>
#include <string>
+#include <thread>
#include <type_traits>
#include <unistd.h>
#include "folly/wangle/Executor.h"
EXPECT_NO_THROW(t.throwIfFailed());
});
}
+
+TEST(Future, waitWithSemaphoreImmediate) {
+ waitWithSemaphore(makeFuture());
+ auto done = waitWithSemaphore(makeFuture(42));
+ EXPECT_EQ(done, 42);
+}
+
+TEST(Future, waitWithSemaphore) {
+ Promise<int> p;
+ Future<int> f = p.getFuture();
+ std::atomic<bool> flag{false};
+ std::atomic<int> result{1};
+ std::atomic<std::thread::id> id;
+
+ std::thread t([&](Future<int>&& tf){
+ auto n = tf.then([&](Try<int> && t) {
+ id = std::this_thread::get_id();
+ return t.value();
+ });
+ flag = true;
+ result.store(waitWithSemaphore(std::move(n)));
+ LOG(INFO) << result;
+ },
+ std::move(f)
+ );
+ while(!flag){}
+ EXPECT_EQ(result.load(), 1);
+ p.setValue(42);
+ t.join();
+ // validate that the continuation ended up executing in this thread, which
+ // is more to ensure that this test actually tests what it should
+ EXPECT_EQ(id, std::this_thread::get_id());
+ EXPECT_EQ(result.load(), 42);
+}