- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
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
添加工作。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_result
、handler_type< 的总体设计的更多详细信息
和 async_completion
。
关于c++ - 如何在其链的上下文中恢复堆栈协程的执行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26694423/
出于好奇 - 我知道有 LAMP - Linux、Apache、MySQL 和 PHP。但是还有哪些其他 Web 堆栈替代方案的缩写呢?像 LAMR - Linux、Apache、MySQL Ruby
我有以下代码。 var stackMapIn = []; var stackMapOut = []; var stackBack = []; stackMapOut.push("m1"); $scop
我遇到了导致我的堆栈无法恢复的情况,我别无选择,只能将其删除。使用完全相同的模板,我继续创建了另一个同名的堆栈。 The following resource(s) failed to create:
这是我第一次查看 Node 堆栈,自从我学习使用 Ruby on Rails 进行 Web 开发以来,我对一些基本的东西有点困惑。我了解 Rails 目录是什么样的。 demo/ ..../app .
本文实例讲述了C语言使用深度优先搜索算法解决迷宫问题。分享给大家供大家参考,具体如下: 深度优先搜索 伪代码 (Pseudocode)如下: ?
我正在按照指南 here ,它告诉我: The stack setup will download the compiler if necessary in an isolatedlocation (
同时 trying to debug a different question ,我安装了一个似乎与我安装的其他一些软件包冲突的软件包。 我跑了 $ stack install regex-pcre-
我花了几个小时创建了一个方法,该方法将从堆栈 s1 中获取 null 元素,并将它们放入 s2 中。然后该类应该打印堆栈。方法如下 import net.datastructures.ArraySta
我有一个类Floor,它有一个Stack block ,但我不知道如何初始化它。我曾尝试过这样的: public class Floor { private Stack stack;
我知道这个问题已经问过很多次了,但搜索一个小时后我仍然遇到问题。 我想使用一个 lifo 堆栈,它可以存储最大数量的元素。达到最大数量后,首先删除该元素并将其替换为新元素,这样在第一次弹出时我可以获取
我需要编写一个方法,压缩以执行以下操作; 目标compress方法是从栈s1中移除所有null元素。剩余(非空)元素应按其初始顺序保留在 s1 上。辅助堆栈 s2 应用作s1 中元素的临时存储。在该方
我正在尝试验证以下代码发生的顺序。 function square(n) { return n * n; } setTimeout(function(){ console.log("H
我需要一个字符数组,其中包含基于特定文件夹中文件数量的动态数量的字符数组。我能够通过初始化 char (*FullPathNames)[MAX_FILENAME_AND_PATHNAME_LENGTH
我正在编写一些日志逻辑并想要进行一些缩进。了解是否存在任何函数调用或某个函数是否已完成的最简单方法是查看堆栈/帧的当前地址。让我们假设堆栈颠倒增长。然后,如果 log() 调用中的堆栈地址小于前一次调
所以内存分段在x86-64中被放弃了,但是当我们使用汇编时,我们可以在代码中指定.code和.data段/段,并且还有堆栈指针寄存器。 还有堆栈段、数据段和代码段寄存器。 代码/数据/堆栈的划分是如何
void main() { int x = 5; // stack-allocated Console.WriteLine(x); } 我知道 x 是堆栈分配的。但是关于 x 的堆栈中
这是我关于 SO 的第一个问题。这可能是一个愚蠢的问题,但到目前为止我还没弄明白。 考虑下面的程序 Reader.java: public class Reader { public
java中有没有一种快速的方法来获取嵌套/递归级别? 我正在编写一个函数来创建组及其成员的列表。成员也可以是团体。我们最终可能会得到一组循环的组/成员。 我想在某个任意级别停止。 我知道我可以将变量保
考虑以下代码: struct A{...}; A a[100]; A* pa = new A[100]; delete[] pa; a/pa 元素的销毁顺序是由标准定义的还是实现定义的(对于第二种情况
我在下面有一些代码。此代码是一个基本的压入/弹出堆栈类,我将其创建为模板以允许某人压入/弹出堆栈。我有一个家庭作业,我现在要做的是创建一个具有多个值的堆栈。 所以我希望能够创建一个基本上可以发送三个整
我是一名优秀的程序员,十分优秀!