Facebook 为 C++11 带来了健壮且强大的 Folly Futures 库

阅读数:4720 2015 年 7 月 30 日

话题:Facebook语言 & 开发

Future 是一种用于同步并发操作的构件,它能够被视为对异步操作结果的只读代理对象,这个对象的初始值是未知的。如果 Future 的客户端试图在操作完成前读取它的值,

可能会被阻塞。Future 通常和一个 Promise 关联,Promise 提供对 Future 的值进行写访问。

异步操作能够立即返回只读的 Future,而不阻塞,示例代码片段如下:

复制代码
#include <folly/futures/Future.h>
using folly::Future;
Future<Output> asyncOperation(Input);
Future<Output> f = asyncOperation(input);

这里的 asyncOperation 是一个异步调用的包装。Future 的客户端能够通过 isReady() 方法检查其关联的 Promise 是否已经完成,并通过 value() 方法获取其结果。

Future 由它关联的 Promise 创建,当异步操作完成时,可以通过 setValue() 或者 setWith() 方法设置它的结果:

复制代码
using folly::Promise;
Future<double> getEnergy(int year) {
auto promise = make_shared<Promise<double>>();
std::thread([=]{
promise->setWith(std::bind(getEnergySync, year));
}).detach();
return promise->getFuture();
}

Folly Futures 库真正强大之处在于其 Future::then 方法,该方法能够方便地进行链式回调,避免进入回调地狱(callback hell)。回调链可以这样来表示:

复制代码
Future<OutputA> futureA(Output);
Future<OutputB> futureB(OutputA);
Future<OutputC> futureC(OutputB);
OutputD d(OutputC) {
if (somethingExceptional) throw anException;
return OutputD();
}
Future<double> fut =
fooFuture(input)
.then(futureA)
.then(futureB)
.then(futureC)
.then(d)
.then([](OutputD outputD) { // 同样支持 lambda 表达式
return outputD * M_PI;
});

Folly Futures 库提供的另一个强大的构建块是集合方法,它允许将 Future 集合视为一个 Future,这个 Future 在集合中的全部 Future 完成时完成。

和集合方法类似,Folly Futures 库还提供了方法:

  • collectAny:当集合中的任何一个 Future 完成时即完成。
  • collectN:等待 N 个 Future 完成后完成。
  • map:参数为 Future 集合和一个函数,针对集合参数中的每个 Future,调用函数参数的 then() 方法。返回值是一个新的 Future 数组。
  • reduce:参数为 Future 集合和带有两个参数的函数(reduce 的值和 reduce 序列中的下一个值),针对集合参数中的每个 Future,依次调用函数参数。

最后,Folly Futures 还支持通过执行上下文来控制回调的执行。例如,你能够给 then 方法传入一个执行器对象,指定此次回调应该通过这个执行器来执行:

复制代码
struct Executor {
using Func = std::function<void()>;
virtual void add(Func) = 0;
};
a(input).then(executor, b);

更多信息可以参见 Folly Future 的文档

查看英文原文:Facebook Folly Brings Robust, Powerful Futures to C++11

()>


感谢丁晓昀对本文的审校。

给 InfoQ 中文站投稿或者参与内容翻译工作,请邮件至editors@cn.infoq.com。也欢迎大家通过新浪微博(@InfoQ@丁晓昀),微信(微信号:InfoQChina)关注我们,并与我们的编辑和其他读者朋友交流(欢迎加入 InfoQ 读者交流群)。