正如您必须知道的那样,鉴于您正在使用它,boost.asio 让您成为其中的一部分。但它不会是一样的。让我解释一下为什么。
node 和 asio 都是围绕 proactor 的思想设计的。如果您想做一些阻塞(或只是缓慢)的事情,您将作业提交给前摄器,它会在适当的时候运行,然后在完成时调用您的回调。
但是在节点中,一切都经过前摄器;没有其他类型的异步 API。如果您想与 MySQL 数据库通信,该接口将采用 SQL 语句并使用行集回叫您。在 C++ 中,接口接受一条 SQL 语句,或者在给你一个游标之前阻塞,或者给你一个可以轮询或阻塞的对象。对于文件和套接字,您可以忽略所有其他 API,例如select
或aio_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
,并非不可行,但它不会像普通的旧线程池和知道如何使用它的并行库那样高效。