我一直在写一些javascript,我喜欢环境的一些事情就是它使用promises/future来为异步事件制作处理程序的方式.
在C++中,你必须在未来调用.get并阻塞,直到将来的结果可用,但在Javascript中你可以写.then(fn),它会在结果准备好时调用函数.重要的是,它在稍后与调用者在同一个线程中执行此操作,因此无需担心线程同步问题,至少与c ++中的问题不同.
我在用c ++思考像 -
auto fut = asyncImageLoader("cat.jpg");
fut.then([](Image img) { std::cout << "Image is now loaded\n" << image; });
Run Code Online (Sandbox Code Playgroud)
有没有办法在c ++中实现这一点?显然,它需要某种事件队列和事件循环来处理调度回调.我最终可能会编写代码来完成大部分工作,但是想看看是否有任何方法可以使用标准工具轻松实现目标.
Com*_*sMS 12
已经为即将到来的C++ 17标准提出了一个.then
函数.std::future
Boost的未来实现(符合当前标准,但提供附加功能作为扩展)已经在较新版本(1.53或更新版本)中提供了该功能的一部分.
有关更完善的解决方案,请查看Boost.Asio库,它允许轻松实现异步控制流future.then
.Asio的概念稍微复杂一些,因为它需要访问中心io_service
对象来调度异步回调,并且需要手动管理工作线程.但原则上这是你所要求的非常好的匹配.
我不喜欢 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;
}
Run Code Online (Sandbox Code Playgroud)
与 Javascript Promise 相比,只是——
你可以解析/拒绝任何类型的参数,而不必关心c++模板中<>的麻烦。
While then
is proposed, you can implement your own infix then
via the named operator technique.
Create a struct then_t {};
and a static then_t then;
. Now override operator*
on the left and right so that std::future<bool> *then* lambda
creates a std::async
that waits on the future
, and passes the result to the lambda
, then returns the return value of the lambda.
这需要大量的关心和关注,因为您必须仔细创建副本以避免悬空引用,并使用 r 和 l 值语法以使其完全高效。
您得到的最终语法是:
aut fut = asyncLoader("cat.jpg");
fut *then* [&](Image img) { std::cout << "Image loaded: " << img; };
Run Code Online (Sandbox Code Playgroud)
这非常接近你想要的。
如果你真的很聪明,你甚至可以让它也支持:
aut fut = asyncLoader("cat.jpg");
fut *then* [=] { std::cout << "Image loaded: " << fut.get(); };
Run Code Online (Sandbox Code Playgroud)
这消除了一些样板,有时会很有用。这需要asyncLoader
返回 astd::shared_future
而不是 a future
。
归档时间: |
|
查看次数: |
5890 次 |
最近记录: |