gpt4 book ai didi

c++ - 如何在其链的上下文中恢复堆栈协程的执行?

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:04:08 29 4
gpt4 key购买 nike

using Yield = asio::yield_context;
using boost::system::error_code;
int Func(Yield yield) {
error_code ec;
asio::detail::async_result_init<Yield, void(error_code, int)> init(yield[ec]);
std::thread th(std::bind(Process, init.handler));
int result = init.result.get(); // <--- yield at here
return result;
}

如何实现 Process 以便 Func 将在 Func 最初生成的链的上下文中恢复?

最佳答案

Boost.Asio 使用辅助函数,asio_handler_invoke , 为调用策略提供自定义点。例如,当处理程序已被 strand 包装时,调用策略将导致处理程序在调用时通过 strand 分派(dispatch)。如 documentation 中所述, asio_handler_invoke 应该通过依赖于参数的查找来调用。

using boost::asio::asio_handler_invoke;
asio_handler_invoke(nullary_functor, &handler);

对于堆栈协程,在生成协程和调用 handler_type 时需要考虑各种重要细节。与 yield_context 相关联恢复协程:

  • 如果代码当前正在协程中运行,则它位于与协程关联的 strand 中。本质上,一个简单的处理程序被恢复协程的 strand 包装,导致执行跳转到协程,阻塞当前在 strand 中的处理程序。当协程让步时,执行跳回到 strand 处理程序,使其完成。
  • 同时 spawn()将工作添加到 io_service(将启动并跳转到协程的处理程序),协程本身不工作。为防止 io_service 事件循环在协程未完成时结束,可能需要在屈服之前向 io_service 添加工作。
  • Stackful 协程使用 strand 帮助保证在调用 resume 之前协程yield。 Asio 1.10.6/Boost 1.58 使能够从启动函数中安全地调用完成处理程序。以前的版本要求完成处理程序不是从启动函数中调用的,因为它的调用策略是dispatch()。 ,导致协程在暂停之前尝试恢复。

这是一个完整的 example这说明了这些细节:

#include <iostream>    // std::cout, std::endl
#include <chrono> // std::chrono::seconds
#include <functional> // std::bind
#include <thread> // std::thread
#include <utility> // std::forward
#include <boost/asio.hpp>
#include <boost/asio/spawn.hpp>

template <typename CompletionToken, typename Signature>
using handler_type_t = typename boost::asio::handler_type<
CompletionToken, Signature>::type;

template <typename Handler>
using async_result = boost::asio::async_result<Handler>;

/// @brief Helper type used to initialize the asnyc_result with the handler.
template <typename CompletionToken, typename Signature>
struct async_completion
{
typedef handler_type_t<CompletionToken, Signature> handler_type;

async_completion(CompletionToken&& token)
: handler(std::forward<CompletionToken>(token)),
result(handler)
{}

handler_type handler;
async_result<handler_type> result;
};

template <typename Signature, typename CompletionToken>
typename async_result<
handler_type_t<CompletionToken, Signature>
>::type
async_func(CompletionToken&& token, boost::asio::io_service& io_service)
{
// The coroutine itself is not work, so guarantee the io_service has
// work.
boost::asio::io_service::work work(io_service);

// Initialize the async completion handler and result.
async_completion<CompletionToken, Signature> completion(
std::forward<CompletionToken>(token));

auto handler = completion.handler;
std::cout << "Spawning thread" << std::endl;
std::thread([](decltype(handler) handler)
{
// The handler will be dispatched to the coroutine's strand.
// As this thread is not running within the strand, the handler
// will actually be posted, guaranteeing that yield will occur
// before the resume.
std::cout << "Resume coroutine" << std::endl;
using boost::asio::asio_handler_invoke;
asio_handler_invoke(std::bind(handler, 42), &handler);
}, handler).detach();

// Demonstrate that the handler is serialized through the strand by
// allowing the thread to run before suspending this coroutine.
std::this_thread::sleep_for(std::chrono::seconds(2));

// Yield the coroutine. When this yields, execution transfers back to
// a handler that is currently in the strand. The handler will complete
// allowing other handlers that have been posted to the strand to run.
std::cout << "Suspend coroutine" << std::endl;
return completion.result.get();
}

int main()
{
boost::asio::io_service io_service;

boost::asio::spawn(io_service,
[&io_service](boost::asio::yield_context yield)
{
auto result = async_func<void(int)>(yield, io_service);
std::cout << "Got: " << result << std::endl;
});

std::cout << "Running" << std::endl;
io_service.run();
std::cout << "Finish" << std::endl;
}

输出:

Running
Spawning thread
Resume coroutine
Suspend coroutine
Got: 42
Finish

有关更多详细信息,请考虑阅读 Library Foundations for Asynchronous Operations .它提供了有关异步操作的组成、Signature 如何影响 async_result 以及 async_resulthandler_type< 的总体设计的更多详细信息async_completion

关于c++ - 如何在其链的上下文中恢复堆栈协程的执行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26694423/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com