像JavaScript这样的c ++期货/承诺?

时间:2014-01-07 14:21:23

标签: c++ promise

我一直在编写一些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 ++中实现这一点?显然,它需要某种事件队列和事件循环来处理调度回调。我最终可能会编写代码来完成大部分工作,但是想看看是否有任何方法可以使用标准工具轻松实现目标。

6 个答案:

答案 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承诺比较,只是 -

  1. 使用newPromise而不是js的新Promise
  2. 使用lambda而不是js function
  3. 使用d.resolve代替js的解决方案
  4. 使用d.reject代替js的拒绝
  5. 您可以使用任何类型的参数来解决/拒绝,并且无需关心&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