C 1Z Coroutine线程上下文和Coroutine调度
C++1z coroutine threading context and coroutine scheduling
根据这一最新C ts:http://www.open-std.org/jtc1/sc222222/wg21/wg21/docs/papers/papers/2016/n4628.pdf,并基于理解在C#async/等待语言支持中,我想知道C Coroutines的"执行上下文"是什么?
我在Visual C 2017 RC中的简单测试代码揭示了Coroutines似乎总是在线程池线程上执行,并且对应用程序开发人员几乎没有控制力可以执行Coroutines的线程上下文,例如。应用程序是否可以迫使所有Coroutines(使用编译器生成的状态机代码)仅在主线程上执行,,,,涉及任何线程池线程?
在C#中,SynchronizationContext是一种指定"上下文"的方法,其中所有coroutine"半"(编译器生成的状态计算机代码)将被发布和执行,如本文中所示:https://blogs.msdn。microsoft.com/pfxteam/2012/01/20/await-synchronizationcontext-and-console-apps/,而当前的Coroutine实现在Visual C 2017 RC中似乎总是依赖并发运行时,默认情况下执行了生成的状态机器线程池线程上的代码。是否存在类似的同步上下文概念,用户应用程序可以用来将Coroutine执行绑定到特定线程?
另外,在Visual C 2017 RC中实现的Coroutines的当前默认"调度程序"是什么?即1)如何准确指定等待条件?2)满足等待条件时,谁调用了悬挂式Coroutine的"下半部分"?
我(幼稚的)关于C#任务调度的猜测是C#纯粹是通过任务延续来实现等待条件 - 候补条件是由taskCompletionsource拥有的任务综合的,任何需要等待的代码逻辑都将被予以予以予以的代码逻辑延续,因此,如果满足等待条件,例如如果从低级别网络处理程序收到了一条完整消息,它将执行任务completionsource.setValue,该消息将基础任务转换为已完成的状态,有效地允许链式的持续逻辑开始执行(将任务从准备好以前创建的状态) - 在C Coroutine中,我猜测STD :: Future and STD :: Promise将被用作类似机制(STD :: Future是任务,而STD :: Promise是TaskCompletionsource,并且用法出乎意料的也很相似!
[edit]:在进行了一些进一步的研究之后,我能够编码一个非常简单但非常有力的抽象,称为"正在等待",该抽象支持单线螺纹和合作的多任务处理,并具有一个基于简单的thread_local基于基于three_local的调度程序,可以在线程上执行coroutines启动了 root coroutine。可以从此GitHub回购中找到代码:https://github.com/llint/awaitable
等待以一种方式保持在嵌套级别的正确调用顺序,并且具有原始的屈服,定时等待和从其他地方准备就绪,并且可以从中衍生出非常复杂的使用模式(例如,无限循环只有在某些事件发生时才会被唤醒的Coroutines,编程模型遵循C#的基于C#的基于HASYNC/等待模式。请随时提供反馈。
相反!
c coroutine全都与控制有关。这里的关键是
void await_suspend(std::experimental::coroutine_handle<> handle)
功能。
evey co_await
期望等待类型。简而言之,等待类型是一种提供这三个功能的类型:
-
bool await_ready()
-程序是否应该阻止执行Coroutine? -
void await_suspend(handle)
-该程序通过该Coroutine框架的延续上下文。如果您激活句柄(例如,通过调用手柄提供的operator ()
- 当前线程立即恢复Coroutine)。 -
T await_resume()
-告诉线程在恢复coroutine时恢复该怎么办,以及从co_await
返回的内容。
因此,当您在等待类型的类型上致电co_await
时,该程序询问等待的coroutine是否应该暂停(如果await_ready
返回false),如果是这样,则您可以在其中做任何可以做的事情。
例如,您可以将Coroutine手柄传递到线池。在这种情况下
您可以将Coroutine手柄传递到简单的std::thread
-您的自己创建线程将恢复Coroutine。
您可以将Coroutine手柄连接到派生的OVERLAPPED
类中,并在异步IO完成时恢复Coroutine。
您可以看到 - 您可以通过管理await_suspend
中传递的Coroutine手柄来控制Coroutine的何时何时暂停并恢复恢复。没有"默认调度程序" - 如何实现您等待类型的类型将决定如何计划。
那么,VC 会发生什么?不幸的是,std::future
仍然没有then
功能,因此您不能将Coroutine手柄传递给std::future
。如果您在std::future
上等待 - 该程序只会打开一个新线程。查看future
标头给出的源代码:
template<class _Ty>
void await_suspend(future<_Ty>& _Fut,
experimental::coroutine_handle<> _ResumeCb)
{ // change to .then when future gets .then
thread _WaitingThread([&_Fut, _ResumeCb]{
_Fut.wait();
_ResumeCb();
});
_WaitingThread.detach();
}
那么,如果在常规std::thread
中启动coroutines,为什么您会看到Win32 ThreadPool-thread?那是因为这不是Coroutine。std::async
在幕后打电话给concurrency::create_task
。默认情况下,在Win32 ThreadPool下启动了concurrency::task
。毕竟,std::async
的全部目的是在另一个线程中启动可可。
- 如何在c++中实现处理器调度模拟器
- 这对"With a stackless coroutine, only the top-level routine may be suspended."意味着什么
- 如何在 C++17 STL 并行算法中处理调度?
- 无法使用迭代器标记调度实例化模板
- 在 c++11 中为 pthread 设置调度参数
- 如何在 assert() 和 static_assert() 之间调度,如果在 constexpr 上下文中依赖?
- 如何使用从处理程序调度的最终回调将响应异步返回给调用方on_read?
- C++双重调度
- 动态调度到模板函数C++
- 正确调度消息 UART
- 在 C++ 中使用枚举而不是结构进行标记调度
- 如何实现从 Windows 脚本主机到脚本的事件调度
- C++内置类型的基于类型的调度
- 恢复ASIO无堆栈Coroutine
- 用于GPU上的瓦片度量和调度的Halide
- SFINAE和标签调度之间的差异
- C++ 如何按标签调度到不同的模板函数
- 在 boost::asio 中发布和调度有什么区别?
- 5 CPU的任务调度N进程
- C 1Z Coroutine线程上下文和Coroutine调度