boost::asio::io_service如何确定工作的优先级

How does boost::asio::io_service prioritize work?

本文关键字:何确定 工作 优先级 service asio io boost      更新时间:2023-10-16

我正在使用boost::asio::io_service来管理一些异步TCP通信。这意味着我创建一个boost::asio::ip::tcp::socket并赋予它io_service。当我开始通信时,它的示意图是这样的:

Async Resolve -> Callback -> Async Connect -> Callback -> Async Write -> Callback -> Async Read

我省略了决心和绑定等部分。假设套接字已绑定到端口并且主机名已解析(因此连接意味着建立与端点的实际连接(

现在的重点是,我可能会使用相同的io_service对象启动多个异步连接。这意味着例如,当我的io_service线程中程序即将Async Write一些数据时,主线程将在 Socket 上调用 Async Resolve(但具有相同的io_service(。这意味着我的io_service现在有一些并行的工作要做 - 我想知道的是它将如何确定工作的优先级?

例如,它是这样的

Main Thread              |      io_service Thread
-------------------------+-----------------------------------------------
SocketA->Async Connect   |
//Some other Stuff       |     SocketA->Callback from Async Connect
                         |     SocketA->Async Write
SocketB->Async Connect   |      
                         |     --> ?

在这一点上,我不得不承认我不太确定io_service是如何工作的。在第四行中,现在需要执行两个不同的异步函数。

io_service能够同时进行Async ConnectAsync Write吗?如果是这种情况,很明显,总是会调用来自首先完成的函数的回调。

如果io_service无法做到这一点,它将按什么顺序完成工作?如果首先调用SocketA Async Write,则也会首先调用它的回调。实际上,在套接字A上的整个操作完成之前,将始终存在工作。

编辑:

根据ereOns的评论,我试图使我的问题更精确一些:

io_service线程的角度来看 - SocketA Async Connect调用是异步的还是同步的?从我的主线程的角度来看,它当然是异步的(它只是调度命令然后继续(。但是在io_service线程中,这个特定的Connect调用会阻止其他操作吗?

换句话说:一个io_service是否能够在读取另一个套接字时连接到一个套接字?

另一个例子是,如果我只在我的 main 函数中调用 2 个Async Connect,则紧接着彼此:

SocketA->AsyncConnect();
SocketB->AsyncConnect();

假设来自套接字 A 的主机有点慢,需要两秒钟才能回答。因此,当套接字A尝试连接时,套接字B是否也会同时连接,还是必须等到套接字A完成/超时?

所有工作都在运行io_service.run()线程中完成。

但是,对任何async_方法的调用都不会阻止此特定线程:它的行为与io_service.run()在多个事件上调用select()完全相同,并且在引发此类事件时"返回"(调用回调(。也就是说,如果您调用:

socketA->async_connect();
socketB->async_connect();

socketB也可以在socketA之前连接,然后首先调用关联的回调,仍在线程io_service.run()运行中。

这就是 Boost Asio 的所有美妙之处:它非常关心投票、等待和在更合适的时候引发事件,留给你"简单"的部分。

您不应该尝试在此处预测异步操作的执行顺序。 async_connect只是向io_service发出信号并立即返回。真正的工作是在对象的事件处理循环(io_service::run(中完成io_service但你不知道确切的细节。它很可能使用特定于操作系统的异步 IO 函数。

目前尚不清楚您要实现的目标。也许您应该使用同步操作。也许您应该使用线程同步功能。也许io_service::run_one会帮助你(它最多执行一个处理程序(。

也许您希望在单独的线程中多次调用io_service::run,从而创建一个线程池。这样,一个长完成处理程序就不会阻止所有其他处理程序。

boost::asio::io_service service;
const size_t ASIO_THREAD_COUNT = 3;
boost::thread_group threadGroup;
for (size_t i = 0; i < ASIO_THREAD_COUNT; ++i)
        threadGroup.create_thread(boost::bind(&boost::asio::io_service::run,
            &service, boost::system::error_code()));