我一直在编写一些javascript,我喜欢环境的一些事情就是它使用promises / futures来为异步事件处理程序。
在C ++中,你必须在未来调用.get,它会阻塞,直到将来的结果可用,但在Javascript中你可以写.then(fn),它会在结果准备好时调用函数。重要的是,它在稍后的调用者的同一个线程中执行此操作,因此不需要担心线程同步问题,至少与c ++中的问题不同。
我在思考c ++之类的东西 -
auto fut = asyncImageLoader("cat.jpg");
fut.then([](Image img) { std::cout << "Image is now loaded\n" << image; });
有没有办法在c ++中实现这一点?显然,它需要某种事件队列和事件循环来处理调度回调。我最终可能会编写代码来完成大部分工作,但是想看看是否有任何方法可以使用标准工具轻松实现目标。
答案 0 :(得分:13)
即将推出的C ++ 17标准.then
的{{1}}函数已proposed。
Boost's implementation of future(符合当前标准,但提供附加功能作为扩展名)已经在较新版本(1.53或更新版本)中提供了该功能的一部分。
对于更完善的解决方案,请查看Boost.Asio library,它允许轻松实现std::future
提供的异步控制流。 Asio的概念稍微复杂一些,因为它需要访问中央future.then
对象来调度异步回调,并且需要手动管理工作线程。但原则上这是你所要求的非常好的匹配。
答案 1 :(得分:4)
虽然提出了then
,但您可以通过命名运算符技术实现自己的中缀then
。
创建struct then_t {};
和static then_t then;
。现在覆盖左侧和右侧的operator*
,以便std::future<bool> *then* lambda
创建一个等待std::async
的{{1}},并将结果传递给future
,然后返回lambda的返回值。
这需要大量的关注和注意,因为你必须仔细创建副本以避免悬空引用,并乱用r和l值语法以使其完全有效。
您得到的最终语法是:
lambda
这非常接近你想要的。
如果你真的很聪明,你甚至可以支持它:
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
。
答案 2 :(得分:3)
我不喜欢c ++的未来,所以我在这里写了一个promise库作为javascript https://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承诺比较,只是 -
您可以使用任何类型的参数来解决/拒绝,并且无需关心&lt;&gt;的麻烦在c ++模板中。
答案 3 :(得分:2)
您可以将一个实现Runnable类的对象传递给Future类的“then”方法。一旦Future完成了它的工作,就调用传递对象的“run”方法。
答案 4 :(得分:0)
看看https://github.com/Naios/continuable。它支持Javascript样式.then()
。它还支持.fail()
(而不是.catch()
)的异常。 https://www.youtube.com/watch?v=l6-spMA_x6g
答案 5 :(得分:0)
这个问题有点老了,但是这里有一个类似于Java的Promise库(由您只需要包含一个标头组成),旨在完全满足您的要求,当然还有某种异步I / O库用于实现实际的asyncImageLoader()
。
https://github.com/alxvasilev/cpp-promise