Skip to content

Instantly share code, notes, and snippets.

@vinniefalco
Created April 16, 2020 20:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vinniefalco/1587e03a851024308cfac07c96f227a3 to your computer and use it in GitHub Desktop.
Save vinniefalco/1587e03a851024308cfac07c96f227a3 to your computer and use it in GitHub Desktop.
As requested, I am reproducing here my email to the author of P1269R0.
Apologies for the use of the second person singular.
---
Hi, I'm the author of Boost.Beast:
<https://github.com/boostorg/beast/>
As such I am heavily invested in both Boost.Asio and Networking.TS. I
offer constructive comments on your paper. I use the general term Asio
to refer to Boost.Asio, stand-alone Asio, and Networking TS. For
reference, this is your paper that I reviewed:
<http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1269r0.html>
> 2. TLS, including native support for SChannel and SecureTransport (not available in ASIO)
You have to write your own stream wrapper, in the style of ssl::stream
which wraps a socket (as does beast::websocket::stream). But if your
algorithms are templated on stream concepts like AsyncReadStream and
AsyncWriteStream, then they will work with custom TLS wrappers right?
I don't see this as a limitation of Asio but rather a strength. Asio's
algorithms should similarly work with your TLS implementation (do
they?)
> 3.1 Synchronous I/O
I agree that synchronous I/O support is limited but I don't think it
was intended for those APIs to provide the same level of functionality
as the asynchronous APIs. They are supposed to be a thin abstraction.
The author has stated many times that timeouts are out of scope for
synchronous I/O. I find this position sensible.
> 3.2 I have strong reservations about the usability of any async framework in C++ built only on top of callbacks.
You might have a point about usability but I do not think usability is
or should be the primary goal of Asio. Instead, it should focus on
providing universal abstractions which allow for nothing in between
itself and the operating system. In other words it should be as low
level as possible while remaining portable. Usability is important but
not when it sacrifices flexibility or performance.
That said, the universal asynchronous model (async_result) mechanism
brilliantly allows primitives other than callbacks to be used such as
futures and coroutines (but you know this). Callbacks are the right
low-level abstraction over the operating system for asynchronous
operations. It should be the responsibility of network middleware
written on top to expose more usable interfaces, with no loss of
performance (other than any performance trade-offs inherent to the
usable interface). This is explained in great detail, in N3747 which
is an excellent read:
<http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3747.pdf>
> 3.3 ...the intermixing of lifetime for socket operations and timers to time them out is difficult to manage...
Well that's putting it mildly...LOL. I am in agreement here. You are
right that adding timeouts to async operations would improve ease of
use but it would also result in an abstraction that is less flexible.
Adding those timeouts would take important decisions about their
implementation away from the user.
Anyway, I have developed a TCP/IP stream wrapper which provides
exactly the feature you want, which is to have an automatic timeout
(currently implemented only for reads). This is accomplished in
async_read_some which will return a custom error code if no activity
occurs. The idea is to be able to just drop it right in, so that any
templated stream algorithm will work with it. You can see that code
here:
<https://github.com/vinniefalco/beast/blob/timeout/include/boost/beast/experimental/core/timed_socket.hpp#L35>
At some point I will refine it and make it part of Beast's
experimental interfaces.
With such an implementation, you could combine it with coroutines or
futures (which already work with Asio and therefore Beast) and get
something which allows you to write code in the synchronous style but
that supports timeouts. I believe this addresses your use-case.
> 3.4.1 Relationship with the Executors TS
Addressed in this paper:
<http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0958r0.html>
> 3.4.2 Over Generalization
Addressed in this paper:
<http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1322r0.html>
> 4.1 Core of the critique
> Without the addition of futures or coroutines, callbacks compose poorly
I couldn't disagree more. Composition is one of the greatest strengths
of Asio's abstractions. In fact I dedicate two tutorials on how to
write them in the Beast documentation:
<https://www.boost.org/doc/libs/1_68_0/libs/beast/doc/html/beast/using_io/writing_composed_operations.html>
<https://www.boost.org/doc/libs/1_68_0/libs/beast/doc/html/beast/using_io/example_detect_ssl.html>
Almost all of your criticisms of Asio can be addressed simply by
gaining proficiency at understanding and writing correct asynchronous
Asio code. Yes I agree that the domain has a certain level of
complexity that cannot be decomposed but Asio's abstractions are in my
opinion, mostly correct.
Regards
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment