Boost logo

Boost :

From: Christopher Kohlhoff (chris_at_[hidden])
Date: 2007-05-03 21:47:08


On Thu, 03 May 2007 16:48:13 -0700, "Jeff Garland"
<jeff_at_[hidden]> 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


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk