首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >基于asio::awaitable实现任务原语

基于asio::awaitable实现任务原语
EN

Stack Overflow用户
提问于 2022-06-14 22:25:44
回答 1查看 162关注 0票数 1

我正在寻找一种方法来实现任务原语,如whenAllwhenAnytaskFromResult,以及(boost) asios awaitable<T> coroutine类型。

到目前为止,我得到的是一个从完成回调创建awaitable<T>的函数。但是,我不确定如何在指定的io_context上并行运行多个任务,并等待所有这些任务,或者直到其中任何一个任务完成。

在.NET中,有一些原语,如Task.WhenAnyTask.WhenAll和类型(如TaskCompletionSource ),它们使处理任务变得更加容易。有人这么做是为了基于asio的协同系统吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-06-15 00:27:54

您可以使用实验操作符重载来组合等待器。

例如。

住在Coliru

代码语言:javascript
运行
复制
#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();
}

印刷品。

代码语言:javascript
运行
复制
foo_or succeeded at 1.00153s
foo_and succeeded at 2.00106s

奖金

使用更多的C++17和默认完成令牌:

代码语言:javascript
运行
复制
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() || ...);
}

现在,您可以提供各种延迟列表:

代码语言:javascript
运行
复制
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

代码语言:javascript
运行
复制
#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();
}

印刷品。

代码语言:javascript
运行
复制
foo_or succeeded at 65ms
foo_and succeeded at 1500ms
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72624023

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档