Fix cppcoro::make_shared_task() for task<void> case.

Work around bug in MSVC by providing special-case overload of
make_shared_task() for task<void>. Add test for this.
This commit is contained in:
Lewis Baker 2017-05-07 22:30:56 +09:30
parent e51997c21d
commit 10fc3b1ecd
2 changed files with 41 additions and 0 deletions

View file

@ -6,6 +6,7 @@
#define CPPCORO_SHARED_TASK_HPP_INCLUDED
#include <cppcoro/broken_promise.hpp>
#include <cppcoro/task.hpp>
#include <atomic>
#include <exception>
@ -461,6 +462,15 @@ namespace cppcoro
{
co_return co_await std::move(t);
}
#if defined(_MSC_VER) && _MSC_FULL_VER <= 191025019
// HACK: Work around bug in MSVC handling of 'co_return <expr>' for void-returning expression.
// It doesn't actually evaluate <expr> before calling <promise>.return_void().
inline shared_task<void> make_shared_task(task<void> t)
{
co_await t;
}
#endif
}
#endif

View file

@ -812,6 +812,36 @@ void testMakeSharedTask()
assert(consumerTask1.is_ready());
}
void testMakeSharedTaskOfVoid()
{
cppcoro::single_consumer_event event;
auto f = [&]() -> cppcoro::task<>
{
co_await event;
};
auto t = cppcoro::make_shared_task(f());
assert(!t.is_ready());
auto consumer = [](cppcoro::shared_task<> task) -> cppcoro::task<>
{
co_await task;
};
auto consumerTask0 = consumer(t);
auto consumerTask1 = consumer(t);
assert(!consumerTask0.is_ready());
assert(!consumerTask1.is_ready());
event.set();
assert(consumerTask0.is_ready());
assert(consumerTask1.is_ready());
}
void testDefaultCancellationTokenIsNotCancellable()
{
cppcoro::cancellation_token t;
@ -1187,6 +1217,7 @@ int main(int argc, char** argv)
testSharedTaskReturningRValueReferenceMovesIntoPromise();
testSharedTaskEquality();
testMakeSharedTask();
testMakeSharedTaskOfVoid();
testDefaultCancellationTokenIsNotCancellable();
testRequestCancellation();