C++中的Resumable功能
[原文发表地址] Resumable functions in C++
[原文发表时间] 2014/11/12 3:35PM
在去年的CTP版本中,我们提供了惊鸿一瞥的resumble功能,并在Visual C++编译器中支持await。在Visual Studio 2015 预览版本中,我们作了进一步的探索之旅,并提供了更常规的解决方案。为执行ISO
C++ 标准,在此预览版本中,我们提供称之为“Resumable functions”的试验性实施方案。这项工作仍在进展之中,但是我们相信这是正确的时间开放讨论这一专题,并从中寻找设计反馈。可以通过这个CppCon视频,了解这一优秀专题概论。该演示的幻灯片在这儿。
在本预览版本中,此功能仅适用于x64。为了使用这一试验性功能,你需要在源文件中包含一些新的头文件(例如"<experimental/resumable>"),并在编译命令行中指定编译选项"/await"。
这项功能建立在协同程序这一概念之上,你可能会在其他语言,(如Python,Ruby等)遇到这一概念。它是一个广义的常规实体,除了支持传统的调用和返回操作外还支持挂起和恢复操作。这非常简单,可以把它想象成为一个方法,不是返回一个调用值,而是在进程中间停止,并把产生的值赋予调用值。下一次调用协同程序时,它在停止位置恢复,直到产生另一个值。
下面是一些示例代码,可以帮助你在此功能的关键点入门:
异步操作
下面的代码片段显示了编码,如函数经历了像科学计算或IO等长时间运算操作后是怎么样的。请注意建议关键字'__await'目的是用于表示等待异步操作的使用结果.
#include <future>
using namespace std;
using namespace std::chrono;
// this could be some long running computation or I/O
future<int> calculate_the_answer()
{
return async([] {
this_thread::sleep_for(1s); return 42;
});
}
// Here is a resumable function
future<void> coro() {
printf("Started waiting... \n");
auto result = __await calculate_the_answer();
printf("got %d. \n", result);
}
int _tmain(int argc, _TCHAR* argv[])
{
coro().get();
}
模式发生器
以下程序片段展现了建议关键字'__yield_value'在模式发生器中的应用。 在模式发生器中,生成协调程序能够将产生的值返回给调用函数,可以根据需求取消这个功能。
#include <iostream> #include <experimental/generator> using namespace std::experimental; using namespace std; generator<int> fib() { int a = 0; int b = 1; for (;;) { __yield_value a; auto next = a + b; a = b; b = next; } } int _tmain(int argc, _TCHAR* argv[]) { for (v : fib()) { if (v > 50) break; cout << v << endl; } }
“活”数据流
以下程序模块展示了建议关键字'for __await'在一种情景中的应用。在此情景中,协作程序(记号)产生异步值流,并有函数(求和)可以消耗这些值流。协同程序时间印章展现了这样一种情景:协调程序对输入流进行消耗,加工,并将它输出给等待它的任意对象。
//As a consumer
future<int> Sum(async_read_stream<int> & input)
{
int result = 0;
for __await(v : input)
{
result += v;
}
return result;
}
//As a producer :
async_generator<int> Ticks()
{
for (int tick = 0;; ++tick)
{
__yield_value tick;
__await sleep_for(1ms);
}
}
//As a transformer : (adds a timestamp to every observed value)
template<class T>
async_generator<pair<T, system_clock::time_point>>
Timestamp(async_read_stream<T> S)
{
for __await(v: S)
__yield_value { v, system_clock::now() };
}
这些都只是该功能的一些例子。我们将继续这方面的工作,希望即将发布的版本,超出预览版本,并希望其有更广的覆盖面,更好的用户体验,支持更高层的开发方案。但是,我们希望你会喜欢目前你所看到的版本,请尽情体验该功能,探索基础概念和功能的新用途。我们期待听到你所有的反馈。