[Boost.Asio] defer, dispatch and post differences?
The free functions *defer*, *dispatch* and *post* all have the exact same set of overloads and description in the library's reference (version 1.66.0). I also couldn't find anything on the subject in the *Overview* section of the library's documentation. Is the differences between them clearly described somewhere else, that I've missed, or could someone explain it? Thank you, Daniel
On Thu, Jan 4, 2018 at 8:46 PM, Daniel Bergström via Boost-users
The free functions defer, dispatch and post all have the exact same set of overloads and description in the library's reference (version 1.66.0).
My understanding is that the post and defer functions replace the old asio_handler_is_continuation mechanism. See: http://www.boost.org/doc/libs/1_66_0/doc/html/boost_asio/net_ts.html Thanks
*post* used to cause the handler to be executed some time in the future on a thread associated with the executor. It was guaranteed not to happen immediately. *dispatch* used to: a. if called by a thread currently associated with the executor, cause the handler to happen now. b. otherwise behave as per post. Has this really changed, or does the documentation have an error? On 5 January 2018 at 08:45, Vinnie Falco via Boost-users < boost-users@lists.boost.org> wrote:
On Thu, Jan 4, 2018 at 8:46 PM, Daniel Bergström via Boost-users
wrote: The free functions defer, dispatch and post all have the exact same set of overloads and description in the library's reference (version 1.66.0).
My understanding is that the post and defer functions replace the old asio_handler_is_continuation mechanism. See:
http://www.boost.org/doc/libs/1_66_0/doc/html/boost_asio/net_ts.html
Thanks _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org https://lists.boost.org/mailman/listinfo.cgi/boost-users
On 5 January 2018 at 10:10, Richard Hodges via Boost-users < boost-users@lists.boost.org> wrote:
*post* used to cause the handler to be executed some time in the future on a thread associated with the executor. It was guaranteed not to happen immediately. *dispatch* used to: a. if called by a thread currently associated with the executor, cause the handler to happen now. b. otherwise behave as per post.
Has this really changed, or does the documentation have an error?
Although it is not supposed to be up to date, I think the description given in the documentation of the executor library that was proposed by the ASIO author is probably the best to understand the difference between these: https://github.com/chriskohlhoff/executors I don't know if there is a difference with the Network TS. A. Joël Lamotte
On Fri, Jan 5, 2018 at 1:52 AM, Klaim - Joël Lamotte via Boost-users
Although it is not supposed to be up to date, I think the description given in the documentation of the executor library that was proposed by the ASIO author is probably the best to understand the difference between these: https://github.com/chriskohlhoff/executors
It really would be nice if Chris Kohlhoff (author of Boost.Asio) could step forward and provide complete detail on how these functions are used, including a few examples such as usage in a composed operation implementation. Thanks
When I had a query regarding the newer standalone boost, I emailed Chris directly. He very helpfully replied promptly and fully. I have always felt that the documentation for ASIO is... terse. Perfect for Mekons, Terminator T2000's and Tron. Not so friendly for human beings. Every piece of information you need is there, exactly once, with not even one character more than is necessary to aid understanding. It took me a few readings for most of it to sink in. I'm still not sure how to code a service's handler invocation properly, so that it will work with futures, handler functions and co-routines (I can at least cause the handler to be posted to the correct io_context and ensure that the context stays 'running' for long enough for it to be executed. I would love to see an example of a fully-fledged asio service implementing, for example, the client side of an http-protocol-socket where the transport is running on a background thread. There are some books on the subject. But they cost, you know, money... On 5 January 2018 at 15:45, Vinnie Falco via Boost-users < boost-users@lists.boost.org> wrote:
Although it is not supposed to be up to date, I think the description given in the documentation of the executor library that was proposed by the ASIO author is probably the best to understand
On Fri, Jan 5, 2018 at 1:52 AM, Klaim - Joël Lamotte via Boost-users
wrote: the difference between these: https://github.com/chriskohlhoff/executors
It really would be nice if Chris Kohlhoff (author of Boost.Asio) could step forward and provide complete detail on how these functions are used, including a few examples such as usage in a composed operation implementation.
Thanks _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org https://lists.boost.org/mailman/listinfo.cgi/boost-users
On Fri, Jan 5, 2018 at 7:21 AM, Richard Hodges via Boost-users
When I had a query regarding the newer standalone boost, I emailed Chris directly. He very helpfully replied promptly and fully.
I emailed him too, several months ago, and this is what I got back: post() -> handler_is_continuation() == false defer() -> handler_is_continuation() == true
Every piece of information you need is there, exactly once, with not even one character more than is necessary to aid understanding.
Yeah I know what you mean. It is quintessentially D.R.Y.. I'll note that Asio does not use defer() anywhere in its implementation. I have not found any code which demonstrates its use. Thanks
I have a feeling that a better reference might be the latest TS document ( http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/n4711.pdf) since that's more likely to be rigorously scrutinised and maintained. defer and dispatch have this to say: " 1 [ Note: The function defer satisfies the requirements for an asynchronous operation (13.2.7), except for the requirement that the operation uses post if it completes immediately. — end note ]" which seems to suggest that defer and dispatch are allowed to invoke the completion handler immediately while post is not. Perhaps defer does a post unless the handler is a continuation? I think that would make sense. R On 5 January 2018 at 16:36, Vinnie Falco via Boost-users < boost-users@lists.boost.org> wrote:
On Fri, Jan 5, 2018 at 7:21 AM, Richard Hodges via Boost-users
wrote: When I had a query regarding the newer standalone boost, I emailed Chris directly. He very helpfully replied promptly and fully.
I emailed him too, several months ago, and this is what I got back:
post() -> handler_is_continuation() == false defer() -> handler_is_continuation() == true
Every piece of information you need is there, exactly once, with not even one character more than is necessary to aid understanding.
Yeah I know what you mean. It is quintessentially D.R.Y..
I'll note that Asio does not use defer() anywhere in its implementation. I have not found any code which demonstrates its use.
Thanks _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org https://lists.boost.org/mailman/listinfo.cgi/boost-users
On 5 January 2018 at 16:55, Vinnie Falco via Boost-users < boost-users@lists.boost.org> wrote:
On Fri, Jan 5, 2018 at 7:53 AM, Richard Hodges via Boost-users
wrote: Perhaps defer does a post unless the handler is a continuation? I think that would make sense.
And how would it know if the handler is a continuation?
I think defer imply that the provided handler is a continuation. There are similar mechanisms proposed in the Executor proposal: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0761r1.pdf (see page 6). Joël Lamotte
Aha: 13.2.2 table 4: x1.defer(std::move(f), a) Effects: Creates an object f1 initialized with DECAY_COPY(std::forward(f)) in the current thread of execution. Calls f1() at most once. The executor shall not block forward progress of the caller pending completion of f1(). The executor should not begin f1’s progress before the call to defer completes. [ Note: One use of defer is to convey the intention of the caller that f1 is a continuation of the current call context. The executor may use this information to optimize or otherwise adjust the way in which f1 is invoked. — end note ] Executor implementations should use the supplied allocator to allocate any memory required to store the function object. Prior to invoking the function object, the executor shall deallocate any memory allocated. [ Note: Executors defined in this Technical Specification always use the supplied allocator unless otherwise specified. — end note ] Synchronization: The invocation of defer synchronizes with (C++ 2014 [intro.multithread]) the invocation of f1. On 5 January 2018 at 17:02, Klaim - Joël Lamotte via Boost-users < boost-users@lists.boost.org> wrote:
On 5 January 2018 at 16:55, Vinnie Falco via Boost-users < boost-users@lists.boost.org> wrote:
On Fri, Jan 5, 2018 at 7:53 AM, Richard Hodges via Boost-users
wrote: Perhaps defer does a post unless the handler is a continuation? I think that would make sense.
And how would it know if the handler is a continuation?
I think defer imply that the provided handler is a continuation. There are similar mechanisms proposed in the Executor proposal: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0761r1.pdf (see page 6).
Joël Lamotte
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org https://lists.boost.org/mailman/listinfo.cgi/boost-users
And how would it know if the handler is a continuation?
Now you're right at the edge of my understanding. I've tried to follow this stuff through in the asio source code previously. As I understand it, you can write your own handler objects, rather than than simply passing in a lambda or bind, which get notified either: 1. once on completion of the entire request, or 2. for every sub-operation of a compound operation such as async_read() asio figures out which one you mean through some template jiggery-pokery (technical term) and your handler gets called the right number of times, on the right thread. But frankly, this stuff has historically been so under-documented (for my simply mind) and written in a WORN (write-once, read-never) combination of macros and template specialisations that I gave up, and limited my ASIO services to simply invoking a handler function on the correct executor and letting the client take it from there. I had hoped to take inspiration from the wonderful but IMHO incomplete AMY wrapper (https://github.com/liancheng/amy) [mysql wrapped in an asio async wrapper]. But Cheng seems to have hit the same wall as me, and you can't handle an async_query with an asio::use_future, for example. Hopefully the TS will clarify all this over time... On 5 January 2018 at 16:55, Vinnie Falco via Boost-users < boost-users@lists.boost.org> wrote:
On Fri, Jan 5, 2018 at 7:53 AM, Richard Hodges via Boost-users
wrote: Perhaps defer does a post unless the handler is a continuation? I think that would make sense.
And how would it know if the handler is a continuation?
Thanks _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org https://lists.boost.org/mailman/listinfo.cgi/boost-users
On Fri, Jan 5, 2018 at 8:05 AM, Richard Hodges via Boost-users
And how would it know if the handler is a continuation?
As I understand it, you can write your own handler objects, rather than than simply passing in a lambda or bind, which get notified either: 1. once on completion of the entire request, or 2. for every sub-operation of a compound operation such as async_read()
asio figures out which one you mean through some template jiggery-pokery (technical term) and your handler gets called the right number of times, on the right thread.
I don't think that is correct. Pre Net-TS, Asio considered a handler to be a continuation if the function asio_handler_is_continuation returned `true` when passed a pointer to an instance of that handler type. The new Asio does not use this mechanism. Instead, it requires that the caller use post() if the handler is not a continuation and defer() if it is. So the caller informs the implementation whether or not the handler is a continuation, just like before but by invoking the correct function. However, it is not clear how to accomplish that. Which is why an example would be helpful. Thanks
Asio considered a handler to be a continuation if the function asio_handler_is_continuation returned `true` when passed a pointer to an instance of that handle
Right, unmaintainable jiggery-pokery
The new Asio does not use this mechanism. Instead, it requires that the caller use post() if the handler is not a continuation and defer() if it is.
Good! *much* more sensible! Thank you. On 5 January 2018 at 17:10, Vinnie Falco via Boost-users < boost-users@lists.boost.org> wrote:
And how would it know if the handler is a continuation?
As I understand it, you can write your own handler objects, rather than
On Fri, Jan 5, 2018 at 8:05 AM, Richard Hodges via Boost-users
wrote: than simply passing in a lambda or bind, which get notified either: 1. once on completion of the entire request, or 2. for every sub-operation of a compound operation such as async_read()
asio figures out which one you mean through some template jiggery-pokery (technical term) and your handler gets called the right number of times, on the right thread.
I don't think that is correct. Pre Net-TS, Asio considered a handler to be a continuation if the function asio_handler_is_continuation returned `true` when passed a pointer to an instance of that handler type. The new Asio does not use this mechanism. Instead, it requires that the caller use post() if the handler is not a continuation and defer() if it is. So the caller informs the implementation whether or not the handler is a continuation, just like before but by invoking the correct function.
However, it is not clear how to accomplish that. Which is why an example would be helpful.
Thanks _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org https://lists.boost.org/mailman/listinfo.cgi/boost-users
On Fri, Jan 05, 2018 at 05:46:21AM +0100, Daniel Bergström via Boost-users wrote:
The free functions *defer*, *dispatch* and *post* all have the exact same set of overloads and description in the library's reference (version 1.66.0). I also couldn't find anything on the subject in the *Overview* section of the library's documentation.
Is the differences between them clearly described somewhere else, that I've missed, or could someone explain it?
I found the following presentation https://chriskohlhoff.github.io/executors/ useful. Dispatch, post and defer are specifically described in slides 15 to 18. F.
participants (5)
-
Daniel Bergström
-
Francesco Giacomini
-
Klaim - Joël Lamotte
-
Richard Hodges
-
Vinnie Falco