Boost logo

Boost Users :

Subject: Re: [Boost-users] [release] Boost 1.67.0 Beta 1
From: Vinnie Falco (vinnie.falco_at_[hidden])
Date: 2018-03-27 00:08:22


On Mon, Mar 26, 2018 at 3:46 PM, Gavin Lambert via Boost-users
<boost-users_at_[hidden]> wrote:
> Out of curiosity, do you have any link to discussion or documents that
> explain the reasoning and/or motivation for this?

The discussion took place privately via email unfortunately.

> I would have assumed that composed operations should not need the equivalent
> of io_service::work because work should be considered in-progress from the
> time that it is originally posted until such time as the completion handler
> *finishes* executing (thus if the completion handler posts additional work,
> there is no "gap").

The composed operation might not call any initiating function and
instead choose to complete immediately, via boost::asio::post. In
Beast for example, this can happen on an HTTP read when the caller's
buffer already has a complete message (no I/O is performed in this
case).

> That's certainly how Asio has historically worked. You only need an
> explicit work guard if there are times when you have no outstanding work
> (eg. you let a completion handler exit without posting something new, or you
> run your io_service/io_context before you post your first operation).

In Net.TS (and by extension, Net.TS-flavored Boost.Asio) work guards
are associated with executors not the io_context. There are two
executors at play here:

1. The executor of the io_context associated with the I/O object
2. The handler's associated executor (obtained by get_associated_executor)

The 2-argument form of boost::asio::post creates the
executor_work_guard for the handler's associated executor, but the
composed operation is responsible for either directly or indirectly
maintaining the lifetime of an executor_work_guard for the
io_context's executor. This is described in [async.reqmts.async.work]:

    13.2.7.10 Outstanding work
    Until the asynchronous operation has completed, the asynchronous
operation shall maintain:
        (1.1) — an object work1 of type executor_work_guard,
initialized as work1(ex1),
            and where work1.owns_work() == true; and
        (1.2) — an object work2 of type executor_work_guard,
initialized as work2(ex2),
            and where work2.owns_work() == true.

See <http://cplusplus.github.io/networking-ts/draft.pdf>

> Or is that last comment indicating that you're using two separate
> io_services, so you do have times where operations aren't pending on one or
> the other?

No, there is only one io_context, which is the io_context associated
with the stream. There are two executors.

Thanks


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net