handle empty task list

This commit is contained in:
Martin Chang 2024-02-03 15:34:39 +08:00
parent df9f28a1a1
commit f981896697
2 changed files with 15 additions and 3 deletions

View File

@ -27,7 +27,6 @@
#include <mutex> #include <mutex>
#include <type_traits> #include <type_traits>
#include <optional> #include <optional>
#include "drogon/DrTemplateBase.h"
namespace drogon namespace drogon
{ {
@ -953,6 +952,9 @@ inline Task<> when_all(std::vector<Awaiter> tasks,
} }
}(eptr, counter, waiter, std::move(task)); }(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; co_await waiter;
if (loop) if (loop)
co_await switchThreadCoro(loop); co_await switchThreadCoro(loop);
@ -1007,6 +1009,9 @@ inline Task<std::vector<await_result_t<Awaiter>>> when_all(
} }
}(eptr, counter, waiter, results, i, std::move(tasks[i])); }(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; co_await waiter;
if (loop) if (loop)
co_await switchThreadCoro(loop); co_await switchThreadCoro(loop);

View File

@ -2,8 +2,6 @@
#include <drogon/utils/coroutine.h> #include <drogon/utils/coroutine.h>
#include <drogon/HttpAppFramework.h> #include <drogon/HttpAppFramework.h>
#include <trantor/net/EventLoopThread.h> #include <trantor/net/EventLoopThread.h>
#include <atomic>
#include <coroutine>
#include <functional> #include <functional>
#include <type_traits> #include <type_traits>
@ -50,6 +48,10 @@ DROGON_TEST(CroutineBasics)
STATIC_REQUIRE(is_int<await_result_t<Task<int>>>::value); STATIC_REQUIRE(is_int<await_result_t<Task<int>>>::value);
STATIC_REQUIRE(is_void<await_result_t<Task<>>>::value); STATIC_REQUIRE(is_void<await_result_t<Task<>>>::value);
// Regular functions should not be awaitable
STATIC_REQUIRE(is_awaitable_v<std::function<void()>> == false);
STATIC_REQUIRE(is_awaitable_v<std::function<int()>> == false);
// No, you cannot await AsyncTask. By design // No, you cannot await AsyncTask. By design
STATIC_REQUIRE(is_awaitable_v<AsyncTask> == false); STATIC_REQUIRE(is_awaitable_v<AsyncTask> == false);
@ -133,6 +135,7 @@ DROGON_TEST(AwaiterTraits)
auto awaiter = sleepCoro(drogon::app().getLoop(), 0.001); auto awaiter = sleepCoro(drogon::app().getLoop(), 0.001);
STATIC_REQUIRE(is_awaitable_v<decltype(awaiter)>); STATIC_REQUIRE(is_awaitable_v<decltype(awaiter)>);
STATIC_REQUIRE(std::is_void<await_result_t<decltype(awaiter)>>::value); STATIC_REQUIRE(std::is_void<await_result_t<decltype(awaiter)>>::value);
sync_wait(awaiter);
} }
DROGON_TEST(CompilcatedCoroutineLifetime) DROGON_TEST(CompilcatedCoroutineLifetime)
@ -289,4 +292,8 @@ DROGON_TEST(WhenAll)
tasks5.emplace_back(std::move(sleep)); tasks5.emplace_back(std::move(sleep));
tasks5.emplace_back(std::move(sleep2)); tasks5.emplace_back(std::move(sleep2));
sync_wait(when_all(std::move(tasks5))); sync_wait(when_all(std::move(tasks5)));
// Check waiting on empty list works
std::vector<Task<>> tasks6;
sync_wait(when_all(std::move(tasks6)));
} }