I am using boost::asio::io_service
to manage some asynchronous TCP communication. That means I create a boost::asio::ip::tcp::socket
and give the io_service
to it. When I start the communication it goes schematically like this:
Async Resolve -> Callback -> Async Connect -> Callback -> Async Write -> Callback -> Async Read
I ommitted parts like resolve and bind. Just assume the Socket has been bound to a port and the hostname is resolved ( so connect meaning establishing the real connection to the endpoint )
Now the point is that I may start several Async Connections with the same io_service
object. This means for example, that while in my io_service
thread the program is about to Async Write
some data, the main thread will call Async Resolve
with on Socket ( but with the same io_service
).
This means that my io_service
now has some parallel work to do - what I'd like to know is how it will prioritize the work?
For example it go like this
Main Thread | io_service Thread
-------------------------+-----------------------------------------------
SocketA->Async Connect |
//Some other Stuff | SocketA->Callback from Async Connect
| SocketA->Async Write
SocketB->Async Connect |
| --> ?
Now at this point I have to admit I am not quite sure how the io_service
works. In the fourth line there are now two different asynchronous functions which needs to be executed.
Is io_service
capable of doing the Async Connect
and the Async Write
simultaneously? If that is the case it is clear that always the callback from the function which is finished first will be called.
If the io_service
is not capable of doing so, in which order will it do the work? If SocketA Async Write
will be called first, it's callback will also be called first. Actually there will be always work until the whole operation on SocketA is finished.
EDIT :
According to ereOns comment I try to make my question a bit more precise:
From the view of the io_service
thread - is the SocketA Async Connect
call asynchronous or synchronous? From the view of my main thread it is of course asynchronous ( it just dispatches the command and then goes on ). But in the io_service
thread will this specific Connect
call block other operations?
In other words: Is one single io_service
capable of Connecting to one Socket while it is reading on another?
Another example would be if I just call 2 Async Connect
in my main function right after each other:
SocketA->AsyncConnect();
SocketB->AsyncConnect();
Let's say the Host from SocketA is a bit slow and it takes it two seconds to answer. So while SocketA is trying to connect would SocketB in the meanwhile also connect or would it have to wait until SocketA is done /timed out?
All the work is done in the thread where io_service.run()
runs.
However, the call to any async_
method won't block this specific thread: it behaves exactly like if io_service.run()
called select()
on several events, and "returns" (calls a callback) whenever such an event is raised. That is, if you call:
socketA->async_connect();
socketB->async_connect();
socketB
may as well connect before socketA
and the associated callback would then be called first, still in the thread io_service.run()
runs.
That's all the beauty of Boost Asio: it takes a very good care about polling, waiting and raising events when it is more appropriate, leaving you with the "easy" part.
You shouldn't try to predict order of execution for asynchronous operations here. async_connect
just signals to io_service
and returns immediately. The real work gets done in io_service
object's event processing loop (io_service::run
), but you don't know exact specifics. It most likely uses OS-specific asynchronous IO functions.
It's not clear what you're trying to achieve. Maybe you should use synchronous operations. Maybe you should use thread synchronization functionality.
Maybe io_service::run_one
will help you (it executes at most one handler).
Maybe you'll want to call io_service::run
multiple times in separate threads, creating a thread pool. That way one long completion handler won't block all the others.
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()));
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With