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() }; 
 } 

       这些都只是该功能的一些例子。我们将继续这方面的工作,希望即将发布的版本,超出预览版本,并希望其有更广的覆盖面,更好的用户体验,支持更高层的开发方案。但是,我们希望你会喜欢目前你所看到的版本,请尽情体验该功能,探索基础概念和功能的新用途。我们期待听到你所有的反馈。

 

公告