像JavaScript这样的C ++期货/承诺
c++ futures/promises like javascript?
我一直在编写一些JavaScript,我喜欢环境的少数几件事之一是它使用promises/futures为异步事件制作处理程序的方式。
在C++中,你必须在未来调用.get,它会阻塞,直到未来的结果可用,但在Javascript中,你可以编写.then(fn),当结果准备好时,它将调用该函数。至关重要的是,它稍后在与调用方相同的线程中执行此操作,因此无需担心线程同步问题,至少与 c++ 中的线程同步问题不同。
我在 c++ 中思考类似的东西 -
auto fut = asyncImageLoader("cat.jpg");
fut.then([](Image img) { std::cout << "Image is now loadedn" << image; });
有没有办法在 c++ 中实现这一点?显然,它将需要某种事件队列和事件循环来处理调度回调。我可能最终可以编写代码来完成大部分工作,但想看看是否有任何方法可以使用标准设施轻松实现目标。
std::future
的.then
函数已被提议用于即将推出的 C++17 标准。
Boost的未来实现(符合当前标准,但提供附加功能作为扩展)已经在较新版本(1.53或更高版本)中提供了部分功能。
有关更完善的解决方案,请查看 Boost.Asio 库,它确实允许轻松实现 future.then
提供的异步控制流。Asio 的概念稍微复杂一些,因为它需要访问用于调度异步回调的中央io_service
对象,并且需要手动管理工作线程。但原则上,这与你所要求的非常匹配。
我不喜欢 c++ 的未来,所以我在这里写了一个 promise 库作为 javascripthttps://github.com/xhawk18/promise-cpp
/* Convert callback to a promise (Defer) */
Defer myDelay(boost::asio::io_service &io, uint64_t time_ms) {
return newPromise([&io, time_ms](Defer &d) {
setTimeout(io, [d](bool cancelled) {
if (cancelled)
d.reject();
else
d.resolve();
}, time_ms);
});
}
void testTimer(io_service &io) {
myDelay(io, 3000).then([&] {
printf("timer after 3000 ms!n");
return myDelay(io, 1000);
}).then([&] {
printf("timer after 1000 ms!n");
return myDelay(io, 2000);
}).then([] {
printf("timer after 2000 ms!n");
}).fail([] {
printf("timer cancelled!n");
});
}
int main() {
io_service io;
testTimer(io);
io.run();
return 0;
}
与Javascript的承诺相比,只是——
- 使用 newPromise 而不是 js 的新 Promise
- 使用 lambda 而不是 js 函数
- 使用 d.resolve 而不是 js 的解析
- 使用 d.reject 而不是 js 的 reject
您可以使用任何类型的参数解析/拒绝,而不必担心 c++ 模板中<>的麻烦。
虽然提出了then
,但您可以通过命名运算符技术实现自己的中缀then
。
创建struct then_t {};
和static then_t then;
。 现在覆盖左右operator*
,以便std::future<bool> *then* lambda
创建一个等待future
的std::async
,并将结果传递给lambda
,然后返回lambda的返回值。
这需要大量的小心和关注,因为您必须仔细创建副本以避免悬而未决的引用,并弄乱 r 和 l 值语法以使其完全有效。
你得到的结束语法是:
aut fut = asyncLoader("cat.jpg");
fut *then* [&](Image img) { std::cout << "Image loaded: " << img; };
这非常接近你想要的。
如果你真的很聪明,你甚至可以让它也支持:
aut fut = asyncLoader("cat.jpg");
fut *then* [=] { std::cout << "Image loaded: " << fut.get(); };
这摆脱了一些样板,有时会很有用。 这要求asyncLoader
返回std::shared_future
而不是future
。
您可以将实现 Runnable 类的对象传递给 Future 类的 "then" 方法。一旦 Future 完成其工作,调用传递对象的 "run" 方法。
看看 https://github.com/Naios/continuable . 它支持Javascript风格的.then()
。 它还支持具有.fail()
(而不是.catch()
)的异常。 这里有一个很好的讨论 https://www.youtube.com/watch?v=l6-spMA_x6g
使用类似 JavaScript 的承诺 for C++20。 它依赖于 C++20 个协程,支持 ES6 await/async 语义,而且非常重要的是,它支持"move",因此您可以为 asio 等框架编写包装器(例如,因为 asio::ip::tcp::socket 无法复制)。
链接: https://github.com/virgil382/JSLikePromise
这个问题有点老了,但这里有一个类似 Javascript 的承诺库(由一个你只需要包含的标头组成),旨在完全按照你的要求去做,当然还有某种异步 I/O 库来实现实际的asyncImageLoader()
。https://github.com/alxvasilev/cpp-promise
- Linux承诺的内存比它所能提供的要多
- 承诺可以使用结构类型吗?
- c++ 线程和承诺
- 从模板生成承诺 可调用
- 存储/传递 v8 承诺解析器供以后使用的最佳实践?(结合C++线程)
- 2个期货之间的依赖关系
- 错误:移动承诺时"Attempt to use a deleted function"
- 使用异步/期货并行和并发计算向量的范数
- 清除所有事物后,所承诺的记忆保持不变
- 在相应的承诺离开范围后有效使用未来
- 如何将自我避难的期货存储在列表中
- STD ::承诺外部代码,异步取消
- STD ::期货和例外
- C++ - 期货向量
- 平行约简(例如求和)hpx::期货<double>的向量
- C++14/17中的懒惰评估-只有lambdas或期货等
- 像JavaScript这样的C ++期货/承诺
- 期货与承诺
- C++11期货/承诺中没有状态错误
- (如何)在C++03中实施期货和承诺?