
On Thu, 03 May 2007 16:48:13 -0700, "Jeff Garland" <jeff@crystalclearsoftware.com> said:
Christopher Kohlhoff wrote:
Yep, Stjepan's correct. You can have a pool of threads calling io_service::run(), and all those threads are considered equivalent when it comes to invoking the completion handlers. I.e. the io_service will just pick any one of them to run the handler.
Ok, I think the docs might deserve just a bit of clarification on this point. Right now it just says:
Multiple threads may call the run() function to set up a pool of threads from which the io_service may execute handlers.
Fair enough. I'll add my above comments to that bit of the docs.
So are you also saying that io_service guarantees that the once a handler is displatched in a thread another request won't interrupt it?
Not sure I completely follow you here, but the io_service will not nest invocation of handlers unless you explicitly request it (by using io_service::dispatch()).
Also, I think I was a bit thrown off by this part of the docs:
The io_service guarantees that the handler will only be called in a thread in which the run() member function is currently being invoked. The handler may be executed inside this function if the guarantee can be met.
which now I'm really not sure I understand :-/
From memory, this text is under io_service::dispatch(), and "this function" refers to io_service::dispatch(). It means that io_service::dispatch works like this:
- Am I in a thread in which io_service::run() is being called? - If yes, invoke handler immediately. - If no, use io_service::post() to defer invocation of handler.
One of the 'interesting' side effects of this behavior, btw, is that you better not write any code where you do something like this:
thread 1 -> a) cretate io_service, b) setup handlers, c) call run; thread 2 -> a) setup handlers, b) do other initialization c) call run;
In thread 2 the handlers will be 'immediately active' because thread 1 has called run already...so the callbacks might happen before the required stop b initialization -- it really needs to be done first.
Yep. In more complicated thread-pool-based use cases I would probably use an io_service::strand to address this. I.e. from thread 2: my_strand.post(setup_stuff); my_io_service.run(); void setup_stuff() { setup handlers to execute in my_strand do other initialisation } This will ensure that the I/O completion handlers aren't called until after setup_stuff() finishes. Cheers, Chris