我正在寻找一种方法来实现任务原语,如whenAll
、whenAny
、taskFromResult
,以及(boost) asios awaitable<T>
coroutine类型。
到目前为止,我得到的是一个从完成回调创建awaitable<T>
的函数。但是,我不确定如何在指定的io_context
上并行运行多个任务,并等待所有这些任务,或者直到其中任何一个任务完成。
在.NET中,有一些原语,如Task.WhenAny
、Task.WhenAll
和类型(如TaskCompletionSource
),它们使处理任务变得更加容易。有人这么做是为了基于asio的协同系统吗?
发布于 2022-06-15 00:27:54
您可以使用实验操作符重载来组合等待器。
例如。
#include <boost/asio.hpp>
#include <boost/asio/awaitable.hpp>
#include <boost/asio/detached.hpp>
#include <boost/asio/experimental/awaitable_operators.hpp>
#include <boost/asio/use_awaitable.hpp>
#include <iostream>
using namespace std::chrono_literals;
auto now = std::chrono::steady_clock::now;
static auto start = now();
using namespace boost::asio::experimental::awaitable_operators;
using boost::asio::awaitable;
using boost::asio::use_awaitable;
using boost::system::error_code;
awaitable<void> foo_and() {
boost::asio::steady_timer tim1(co_await boost::asio::this_coro::executor, 1s);
boost::asio::steady_timer tim2(co_await boost::asio::this_coro::executor, 2s);
co_await (tim1.async_wait(use_awaitable) && tim2.async_wait(use_awaitable));
}
awaitable<void> foo_or() {
boost::asio::steady_timer tim1(co_await boost::asio::this_coro::executor, 1s);
boost::asio::steady_timer tim2(co_await boost::asio::this_coro::executor, 2s);
co_await (tim1.async_wait(use_awaitable) || tim2.async_wait(use_awaitable));
}
int main() {
boost::asio::io_context ioc;
auto handler = [](auto caption) {
return [=](std::exception_ptr e) {
try {
if (e)
std::rethrow_exception(e);
std::cout << caption << " succeeded at ";
} catch (std::exception const& e) {
std::cout << caption << " failed at ";
}
std::cout << (now() - start) / 1.0s << "s" << std::endl;
};
};
co_spawn(ioc.get_executor(), foo_and(), handler("foo_and"));
co_spawn(ioc.get_executor(), foo_or(), handler("foo_or"));
ioc.run();
}
印刷品。
foo_or succeeded at 1.00153s
foo_and succeeded at 2.00106s
奖金
使用更多的C++17和默认完成令牌:
awaitable<void> foo_and(auto... delays) {
auto ex = co_await boost::asio::this_coro::executor;
co_await(Timer(ex, delays).async_wait() && ...);
}
awaitable<void> foo_or(auto... delays) {
auto ex = co_await boost::asio::this_coro::executor;
co_await(Timer(ex, delays).async_wait() || ...);
}
现在,您可以提供各种延迟列表:
co_spawn(ioc.get_executor(), foo_and(100ms, 1500ms, 75ms), handler("foo_and"));
co_spawn(ioc.get_executor(), foo_or(1s, 5min, 65ms), handler("foo_or"));
看吧,住在Coliru
#include <boost/asio.hpp>
#include <boost/asio/awaitable.hpp>
#include <boost/asio/detached.hpp>
#include <boost/asio/experimental/awaitable_operators.hpp>
#include <boost/asio/use_awaitable.hpp>
#include <iostream>
using namespace std::chrono_literals;
auto now = std::chrono::steady_clock::now;
static auto start = now();
using namespace boost::asio::experimental::awaitable_operators;
using boost::asio::awaitable;
using boost::asio::use_awaitable;
using boost::system::error_code;
using Timer = boost::asio::use_awaitable_t<>::as_default_on_t<boost::asio::steady_timer>;
awaitable<void> foo_and(auto... delays) {
auto ex = co_await boost::asio::this_coro::executor;
co_await(Timer(ex, delays).async_wait() && ...);
}
awaitable<void> foo_or(auto... delays) {
auto ex = co_await boost::asio::this_coro::executor;
co_await(Timer(ex, delays).async_wait() || ...);
}
int main() {
boost::asio::io_context ioc;
auto handler = [](auto caption) {
return [=](std::exception_ptr e) {
try {
if (e)
std::rethrow_exception(e);
std::cout << caption << " succeeded at ";
} catch (std::exception const& e) {
std::cout << caption << " failed at ";
}
std::cout << (now() - start) / 1ms << "ms" << std::endl;
};
};
co_spawn(ioc.get_executor(), foo_and(100ms, 1500ms, 75ms), handler("foo_and"));
co_spawn(ioc.get_executor(), foo_or(1s, 5min, 65ms), handler("foo_or"));
ioc.run();
}
印刷品。
foo_or succeeded at 65ms
foo_and succeeded at 1500ms
https://stackoverflow.com/questions/72624023
复制相似问题