18 #if FOLLY_HAS_COROUTINES 30 #include <type_traits> 55 "blockingWait() should convert rvalue-reference-returning awaitables " 56 "into a returned prvalue to avoid potential lifetime issues since " 57 "its possible the rvalue reference could have been to some temporary " 58 "object stored inside the Awaiter which would have been destructed " 59 "by the time blockingWait returns.");
61 TEST(BlockingWait, SynchronousCompletionVoidResult) {
65 TEST(BlockingWait, SynchronousCompletionPRValueResult) {
74 TEST(BlockingWait, SynchronousCompletionLValueResult) {
82 TEST(BlockingWait, SynchronousCompletionRValueResult) {
83 auto p = std::make_unique<int>(123);
95 struct TrickyAwaitable {
97 std::unique_ptr<int> value_;
99 bool await_ready()
const {
103 bool await_suspend(std::experimental::coroutine_handle<>) {
104 value_ = std::make_unique<int>(42);
108 std::unique_ptr<int>&& await_resume() {
113 Awaiter
operator co_await() {
118 TEST(BlockingWait, ReturnRvalueReferenceFromAwaiter) {
126 CHECK_EQ(42, *result);
129 TEST(BlockingWait, AsynchronousCompletionOnAnotherThread) {
131 std::thread
t{[&] { baton.
post(); }};
138 template <
typename T>
139 class SimplePromise {
141 class WaitOperation {
143 explicit WaitOperation(
146 : awaiter_(baton), value_(value) {}
149 return awaiter_.await_ready();
152 template <
typename Promise>
153 auto await_suspend(std::experimental::coroutine_handle<Promise>
h) {
154 return awaiter_.await_suspend(h);
158 awaiter_.await_resume();
167 SimplePromise() =
default;
169 WaitOperation
operator co_await() {
170 return WaitOperation{baton_, value_};
173 template <
typename...
Args>
174 void emplace(
Args&&... args) {
175 value_.emplace(static_cast<Args&&>(args)...);
184 TEST(BlockingWait, WaitOnSimpleAsyncPromise) {
185 SimplePromise<std::string> p;
186 std::thread
t{[&] { p.emplace(
"hello coroutines!"); }};
194 struct MoveCounting {
196 MoveCounting()
noexcept : count_(0) {}
197 MoveCounting(MoveCounting&& other)
noexcept : count_(other.count_ + 1) {}
198 MoveCounting& operator=(MoveCounting&& other) =
delete;
201 TEST(BlockingWait, WaitOnMoveOnlyAsyncPromise) {
202 SimplePromise<MoveCounting> p;
203 std::thread
t{[&] { p.emplace(); }};
217 TEST(BlockingWait, moveCountingAwaitableReady) {
229 TEST(BlockingWait, WaitInFiber) {
230 SimplePromise<int> promise;
#define TEST(test_case_name, test_name)
#define EXPECT_EQ(val1, val2)
constexpr detail::Map< Move > move
internal::ArgsMatcher< InnerMatcher > Args(const InnerMatcher &matcher)
requires E e noexcept(noexcept(s.error(std::move(e))))
#define EXPECT_GE(val1, val2)
bool loopOnce(int flags=0)
static const char *const value
#define EXPECT_TRUE(condition)
#define EXPECT_FALSE(condition)
auto blockingWait(Awaitable &&awaitable) -> detail::decay_rvalue_reference_t< await_result_t< Awaitable >>
FiberManager & getFiberManager(EventBase &evb, const FiberManager::Options &opts)