我在最后几天编写node.js并大量使用异步library。它是一个库,它引入了处理异步编程中常见工作流的函数。有些函数可以并行或在另一个之后运行异步调用,并在所有函数完成后调用单个回调(或发生错误)。
C ++有没有这样的图书馆?
我非常喜欢异步编程,但是大量的回调(所有这些都有错误处理等)都很难阅读和维护,并且有点难看。我希望按照我对异步库的体验继续编码。
我想这样的库在C ++等动态类型较少的语言中难以实现。
PS:建议如何使异步代码更漂亮也欢迎。
编辑:我正在使用g ++和C ++ 11。
编辑2:“异步”意味着在此上下文中使用带有回调的非阻塞函数,而不是在后台运行并行线程。一个例子是boost:asio。
编辑3:我已经在使用boost :: asio,并希望用这样的库来增强代码的可读性(控制流的清晰度......)。
答案 0 :(得分:5)
正如你必须已经知道的那样,鉴于你正在使用它,boost.asio会让你成为那里的一部分。但它不会是一样的。让我解释一下原因。
node和asio都是围绕一个proactor的想法而设计的。如果你想做一些阻塞(或者只是缓慢)的事情,你将工作提交给proactor,它会在适当的时候运行,然后在它完成时调用你的回调。
但是在节点中,所有都通过了预测器;没有其他类型的异步API。如果你想与MySQL数据库通信,接口将获取一个SQL语句并使用行集回调。在C ++中,接口接受一个SQL语句,并在给出游标之前阻塞,或者为您提供一个可以轮询或阻止的对象。对于文件和套接字,您可以忽略所有其他API,如select
或aio_read
,因为asio有完整的包装器,但对于其他任何事情,您必须完成编写包装器的工作,而且通常是很多工作。
更严重的是,节点中的标准回调接口是callback(error, result)
,其中result
是JS对象,可以包含任何适当的成员。 asio中的标准回调接口是void callback(const error_code&)
,其中 没有结果。您将可变对象绑定到任务中。这已经使得控制流程变得更加笨拙,因为对象无法在不知道其前任如何隐藏其可变数据的情况下跟随另一个对象。这也意味着您需要共享的可变数据(与节点不同,可以跨线程共享),无论您是否需要它。但当然最大的问题是数据是静态类型的。 (通常人们构建C ++类,并通过将任务绑定到同一对象的方法来共享状态,但这实际上并不是必需的。)
当然,您可以编写代码来完成C ++中的完全动态对象(或者只是一个动态级别,就像vector<boost::any>
就足够了),但它仍然比使用JS更加笨拙,并且你将通过转向C ++来放弃你希望获得的大部分性能优势。
因此,编写像void async::waterfall(vector<void(const error_code&)>> tasks)
这样与async.waterfall(tasks)
完全相同的函数会非常容易,但它不会为您提供所需的所有好处。< / p>
需要考虑的另一点是,您已经切换到C ++是有原因的:您处于一个缓慢的,资源受限的系统中。使用一个proactor来实现数据并行性,相当于async.forEach
,并不是不可行的,但它不会像普通的旧线程池和知道如何使用它的并行库一样高效。
答案 1 :(得分:2)
只需使用C ++即可。 std::async
完成这项工作。除标准C ++库之外不需要(需要C ++ 11,已经在几个编译器中实现)
答案 2 :(得分:2)
在谈到异步和C ++时,asio出现在我的脑海中。该库专注于异步I / O,但也允许编写与框架一起使用的自定义“服务”(例如this example中所示)。
答案 3 :(得分:1)