C++ 了解C+提案N3650中关于可恢复功能的示例+;1y
考虑以下示例,该示例取自: 我可能遗漏了一些东西,但是如果我理解了C++ 了解C+提案N3650中关于可恢复功能的示例+;1y,c++,c++14,C++,C++14,考虑以下示例,该示例取自: 我可能遗漏了一些东西,但是如果我理解了async和wait那么,当效果等同于写作时,用上面的例子展示这两种结构的有用性有什么意义呢 int cnt = 0; do { cnt = streamR.read(512, buf).get(); if (cnt == 0) break; cnt = streamW.write(cnt, buf).get(); } while (cnt > 0); 如果read().get()和write
async
和wait
那么,当效果等同于写作时,用上面的例子展示这两种结构的有用性有什么意义呢
int cnt = 0;
do {
cnt = streamR.read(512, buf).get();
if (cnt == 0)
break;
cnt = streamW.write(cnt, buf).get();
} while (cnt > 0);
如果
read().get()
和write().get()
调用都是同步的?我认为想法是streamR.read()
和streamW.write()
调用是异步I/O操作和返回未来,由wait
表达式自动等待
因此,等效的同步版本必须调用future::get()
来获得结果,例如
int cnt = 0;
do {
cnt = streamR.read(512, buf).get();
if (cnt == 0)
break;
cnt = streamW.write(cnt, buf).get();
} while (cnt > 0);
您指出这里没有并发是正确的。但是,在可恢复函数的上下文中,wait
使行为与上面的代码片段不同。当到达wait
时,函数将返回一个future
,因此即使可恢复函数在等待其他结果时在wait
处被阻止,函数调用方也可以继续而不阻塞(例如,在这种情况下,read()
或write()
调用以完成)Resubable函数可能会异步恢复运行,因此当调用方执行其他操作时,结果在后台可用。更完整的示例(希望正确):
不同之处在于可恢复函数可以由不同的线程执行:不同的线程可以在每个恢复/暂停点之后恢复(可恢复函数的)执行。等待关键字不等于在将来调用get。你可以这样看,假设你从这个开始:
future<T> complex_function()
{
do_some_stuff();
future<Result> x = await some_async_operation();
return do_some_other_stuff(x);
}
future复数函数()
{
做些什么;
future x=等待一些异步操作();
返回做一些其他事情(x);
}
这在功能上与
future<T> complex_function()
{
do_some_stuff();
return some_async_operation().then([=](future<Result> x) {
return do_some_other_stuff(x);
});
}
future复数函数()
{
做些什么;
返回一些异步操作()。然后([=](未来x){
返回做一些其他事情(x);
});
}
请或多或少注意,由于存在一些资源管理方面的影响,在do_some_stuff
中创建的变量不应复制到执行do_some_other_stuff
中,就像lambda版本一样
第二个变量更清楚地说明了调用时会发生什么
complex\u函数时,将同步调用do\u some\u stuff()
某些异步操作被异步调用,并在将来产生结果。执行此操作的确切时间取决于实际的异步调用实现,它可能在使用线程时立即执行,也可能在使用延迟执行时调用.get()
时立即执行李>
我们不会立即执行do\u some\u other\u stuff
,而是将其链接到步骤2中获得的未来。这意味着只要某个异步操作的结果准备就绪,就可以执行该操作,但不能在此之前执行。除此之外,它的执行时刻由运行时决定。如果实施仅包装,则
提案,这意味着它将继承未来母公司的执行人/启动政策(根据N3558)
函数返回表示最终结果的最后一个未来。注意,这需要是将来的事情,因为函数体的一部分是异步执行的
下面是不使用wait的示例函数的正确翻译:
struct Copy$StackFrame {
promise<void> $result;
input_stream& streamR;
output_stream& streamW;
int cnt;
char buf[512];
};
using Copy$StackPtr = std::shared_ptr<Copy$StackFrame>;
future<void> Copy(input_stream& streamR, output_stream& streamW) {
Copy$StackPtr $stack{ new Copy$StackFrame{ {}, streamR, streamW, 0 } };
future<int> f$1 = $stack->streamR.read(512, stack->buf);
f$1.then([$stack](future<int> f) { Copy$Cont1($stack, std::move(f)); });
return $stack->$result.get_future();
}
void Copy$Cont1(Copy$StackPtr $stack, future<int> f$1) {
try {
$stack->cnt = f$1.get();
if ($stack->cnt == 0) {
// break;
$stack->$result.set_value();
return;
}
future<int> f$2 = $stack->streamW.write($stack->cnt, $stack->buf);
f$2.then([$stack](future<int> f) { Copy$Cont2($stack, std::move(f)); });
} catch (...) {
$stack->$result.set_exception(std::current_exception());
}
}
void Copy$Cont2(Copy$StackPtr $stack, future<int> f$2) {
try {
$stack->cnt = f$2.get();
// while (cnt > 0)
if (cnt <= 0) {
$stack->$result.set_value();
return;
}
future<int> f$1 = $stack->streamR.read(512, stack->buf);
f$1.then([$stack](future<int> f) { Copy$Cont1($stack, std::move(f)); });
} catch (...) {
$stack->$result.set_exception(std::current_exception());
}
}
struct Copy$StackFrame{
承诺$结果;
输入流&streamR;
输出流&streamW;
int-cnt;
char-buf[512];
};
使用Copy$StackPtr=std::shared\u ptr;
未来副本(输入流和流器、输出流和流器){
复制$StackPtr$stack{new Copy$StackFrame{{},streamR,streamW,0};
未来f$1=$stack->streamR.read(512,stack->buf);
f$1。然后([$stack](未来f){Copy$Cont1($stack,std::move(f));});
返回$stack->$result.get_future();
}
无效副本$Cont1(副本$StackPtr$stack,未来f$1){
试一试{
$stack->cnt=f$1.get();
如果($stack->cnt==0){
//中断;
$stack->$result.set_value();
返回;
}
未来f$2=$stack->streamW.write($stack->cnt,$stack->buf);
然后([$stack](未来的f){Copy$Cont2($stack,std::move(f));});
}捕获(…){
$stack->$result.set_异常(std::current_exception());
}
}
无效副本$Cont2(副本$StackPtr$stack,未来f$2){
试一试{
$stack->cnt=f$2.get();
//而(cnt>0)
如果(cnt$result.set_value();
返回;
}
未来f$1=$stack->streamR.read(512,stack->buf);
f$1。然后([$stack](未来f){Copy$Cont1($stack,std::move(f));});
}捕获(…){
$stack->$result.set_异常(std::current_exception());
}
}
正如您所看到的,这里的编译器转换非常复杂
版本,原始的副本
在第一次异步调用完成后立即返回其未来。对于这两个代码示例之间的差异的含义,我有相同的问题。让我们重新编写一点,以便更完整
// Having two functions
future<void> f (istream&streamR, ostream&streamW) async
{ int cnt = 0;
do {
cnt = await streamR.read(512, buf);
if (cnt == 0)
break;
cnt = await streamW.write(cnt, buf);
} while (cnt > 0);
}
void g(istream&streamR, ostream&streamW)
{ int cnt = 0;
do {
cnt = streamR.read(512, buf).get();
if (cnt == 0)
break;
cnt = streamW.write(cnt, buf).get();
} while (cnt > 0);
}
// what is the difference between
auto a = f(streamR, streamW);
// and
auto b = async(g, streamR, streamW);
//有两个函数
未来f(istream和streamR、ostream和streamW)异步
{int cnt=0;
做{
cnt=等待流读取(512,buf);
如果(cnt==0)
打破
cnt=等待流w.write(cnt,buf);
}而(cnt>0);
}
空隙g(istream&streamR、ostream&streamW)
{int cnt=0;
做{
cnt=streamR.read(512,buf.get();
如果(cnt==0)
打破
cnt=streamW.write(cnt,buf.get();
}而(cnt>0);
}
//两者的区别是什么
自动a=f(流线型,st
future<T> complex_function()
{
do_some_stuff();
return some_async_operation().then([=](future<Result> x) {
return do_some_other_stuff(x);
});
}
struct Copy$StackFrame {
promise<void> $result;
input_stream& streamR;
output_stream& streamW;
int cnt;
char buf[512];
};
using Copy$StackPtr = std::shared_ptr<Copy$StackFrame>;
future<void> Copy(input_stream& streamR, output_stream& streamW) {
Copy$StackPtr $stack{ new Copy$StackFrame{ {}, streamR, streamW, 0 } };
future<int> f$1 = $stack->streamR.read(512, stack->buf);
f$1.then([$stack](future<int> f) { Copy$Cont1($stack, std::move(f)); });
return $stack->$result.get_future();
}
void Copy$Cont1(Copy$StackPtr $stack, future<int> f$1) {
try {
$stack->cnt = f$1.get();
if ($stack->cnt == 0) {
// break;
$stack->$result.set_value();
return;
}
future<int> f$2 = $stack->streamW.write($stack->cnt, $stack->buf);
f$2.then([$stack](future<int> f) { Copy$Cont2($stack, std::move(f)); });
} catch (...) {
$stack->$result.set_exception(std::current_exception());
}
}
void Copy$Cont2(Copy$StackPtr $stack, future<int> f$2) {
try {
$stack->cnt = f$2.get();
// while (cnt > 0)
if (cnt <= 0) {
$stack->$result.set_value();
return;
}
future<int> f$1 = $stack->streamR.read(512, stack->buf);
f$1.then([$stack](future<int> f) { Copy$Cont1($stack, std::move(f)); });
} catch (...) {
$stack->$result.set_exception(std::current_exception());
}
}
// Having two functions
future<void> f (istream&streamR, ostream&streamW) async
{ int cnt = 0;
do {
cnt = await streamR.read(512, buf);
if (cnt == 0)
break;
cnt = await streamW.write(cnt, buf);
} while (cnt > 0);
}
void g(istream&streamR, ostream&streamW)
{ int cnt = 0;
do {
cnt = streamR.read(512, buf).get();
if (cnt == 0)
break;
cnt = streamW.write(cnt, buf).get();
} while (cnt > 0);
}
// what is the difference between
auto a = f(streamR, streamW);
// and
auto b = async(g, streamR, streamW);