diff --git a/lib/inc/drogon/utils/coroutine.h b/lib/inc/drogon/utils/coroutine.h index 484dc12f..036db2e6 100644 --- a/lib/inc/drogon/utils/coroutine.h +++ b/lib/inc/drogon/utils/coroutine.h @@ -27,7 +27,6 @@ #include #include #include -#include "drogon/DrTemplateBase.h" namespace drogon { @@ -953,6 +952,9 @@ inline Task<> when_all(std::vector tasks, } }(eptr, counter, waiter, std::move(task)); } + // In case there's no task, we should still wait for the notify + if (tasks.empty()) + waiter.notify(); co_await waiter; if (loop) co_await switchThreadCoro(loop); @@ -1007,6 +1009,9 @@ inline Task>> when_all( } }(eptr, counter, waiter, results, i, std::move(tasks[i])); } + // In case there's no task, we should still wait for the notify + if (tasks.empty()) + waiter.notify(); co_await waiter; if (loop) co_await switchThreadCoro(loop); diff --git a/lib/tests/unittests/CoroutineTest.cc b/lib/tests/unittests/CoroutineTest.cc index 1d75bb4f..1a32860f 100644 --- a/lib/tests/unittests/CoroutineTest.cc +++ b/lib/tests/unittests/CoroutineTest.cc @@ -2,8 +2,6 @@ #include #include #include -#include -#include #include #include @@ -50,6 +48,10 @@ DROGON_TEST(CroutineBasics) STATIC_REQUIRE(is_int>>::value); STATIC_REQUIRE(is_void>>::value); + // Regular functions should not be awaitable + STATIC_REQUIRE(is_awaitable_v> == false); + STATIC_REQUIRE(is_awaitable_v> == false); + // No, you cannot await AsyncTask. By design STATIC_REQUIRE(is_awaitable_v == false); @@ -133,6 +135,7 @@ DROGON_TEST(AwaiterTraits) auto awaiter = sleepCoro(drogon::app().getLoop(), 0.001); STATIC_REQUIRE(is_awaitable_v); STATIC_REQUIRE(std::is_void>::value); + sync_wait(awaiter); } DROGON_TEST(CompilcatedCoroutineLifetime) @@ -289,4 +292,8 @@ DROGON_TEST(WhenAll) tasks5.emplace_back(std::move(sleep)); tasks5.emplace_back(std::move(sleep2)); sync_wait(when_all(std::move(tasks5))); + + // Check waiting on empty list works + std::vector> tasks6; + sync_wait(when_all(std::move(tasks6))); }