2

最近几天我在编程 node.js 并且大量使用了异步。它是一个库,它引入了处理异步编程中常见工作流的函数。有些函数并行或依次运行异步调用,并在所有函数完成(或发生错误)后调用单个回调。

有没有这样的 C++ 库?

我真的很喜欢异步编程,但是大量的回调(它们都带有错误处理等)真的很难阅读和维护,而且有点难看。我很想继续以我使用异步库的方式进行编码。

我想这样的库更难用像 C++ 这样动态类型较少的语言来实现。

PS:也欢迎提出如何使异步代码更漂亮的建议。

编辑:我在 C++11 中使用 g++。

编辑2:“异步”意味着在这种情况下使用带有回调的非阻塞函数,而不是在后台运行并行线程。一个例子是 boost:asio。

编辑 3:我已经在使用 boost::asio 并希望使用这样的库来增强代码的可读性(控制流的清晰度,...)。

4

4 回答 4

6

正如您必须知道的那样,鉴于您正在使用它,boost.asio 让您成为其中的一部分。但它不会是一样的。让我解释一下为什么。

node 和 asio 都是围绕 proactor 的思想设计的。如果您想做一些阻塞(或只是缓慢)的事情,您将作业提交给前摄器,它会在适当的时候运行,然后在完成时调用您的回调。

但是在节点中,一切都经过前摄器;没有其他类型的异步 API。如果您想与 MySQL 数据库通信,该接口将采用 SQL 语句并使用行集回叫您。在 C++ 中,接口接受一条 SQL 语句,或者在给你一个游标之前阻塞,或者给你一个可以轮询或阻塞的对象。对于文件和套接字,您可以忽略所有其他 API,例如selectaio_read因为 asio 具有完整的包装器,但对于几乎所有其他东西,您必须完成编写包装器的工作,而且通常需要做很多工作。

更严重的是,node 中的标准回调接口是callback(error, result),其中result是一个 JS 对象,可以有任何合适的成员。asio 中的标准回调接口是void callback(const error_code&),这里没有结果。您将可变对象绑定到任务中。这已经使控制流变得更加笨拙,因为一个对象不可能在不知道其前身如何隐藏其可变数据的情况下跟随另一个对象。这也意味着您需要共享可变数据(与节点不同,它可以跨线程共享),无论您是否愿意。但当然最大的问题是数据是静态类型的。(通常人们构建 C++ 类,并通过将任务绑定到同一对象的方法来共享状态,但这实际上并不是必需的。)

当然,您可以编写代码以在 C++ 中实现完全动态的对象(或者可能只使用一级动态性,例如 avector<boost::any>就足够了),但它仍然比在 JS 中使用起来更笨拙,而且您将放弃很多您希望通过迁移到 C++ 获得的性能优势。

void async::waterfall(vector<void(const error_code&)>> tasks)因此,编写与完全相同的函数会很容易async.waterfall(tasks),但它不会为您带来您正在寻找的所有相同的好处。

要考虑的另一点是,您切换到 C++ 是有原因的:您使用的是一个缓慢、资源受限的系统。使用前摄器来实现数据并行性,相当于async.forEach,并非不可行,但它不会像普通的旧线程池和知道如何使用它的并行库那样高效。

于 2012-09-28T18:11:58.967 回答
3

只需使用 C++。std::async做这项工作。不需要标准 C++ 库(需要 C++11,已经在多个编译器中实现)

于 2012-09-28T08:56:46.480 回答
2

当谈到异步和 C++ 时,我想到了asio 。该库专注于异步 I/O,但也允许编写自定义“服务”以与框架一起使用(如本示例所示)。

于 2012-09-28T09:00:24.263 回答
1

虽然我个人会接受 Walter 对 C++11 标准库的推荐,但我还想指出

提升亚西欧

为了完整性。

于 2012-09-28T09:08:08.163 回答