[Boost-users] Networking TS + Beast, NEW Tutorials, Read this to learn std::net !!!

106 views
Skip to first unread message

Vinnie Falco via Boost-users

unread,
Mar 14, 2019, 12:48:51 PM3/14/19
to C++ Library Evolution Working Group, Boost users list, boost@lists.boost.org List, Vinnie Falco
Fellow C++, Boost, and WG21 Enthusiasts, lend me your ear!

I write to inform you about exciting developments in C++ networking.

First, a bit of background. Networking comes in three flavors:

* Networking TS <https://cplusplus.github.io/networking-ts/draft.pdf>
* Boost.Asio <https://www.boost.org/doc/libs/1_69_0/doc/html/boost_asio.html>
* Standalone Asio <https://github.com/chriskohlhoff/asio>

These three are for the most part identical, except that Asio flavors
have additional features like ssl::stream and signal_set which are not
in the TS, but will very likely appear in a future update or version.
We've had Asio for over a decade now, but there is a shortage of
experts. Some people believe this shortage is because Asio in
particular (and thus, Networking TS since they have identical
interfaces) is "difficult to use." I believe it is wrong to blame Asio
for this. Concurrent programs in general are hard to write. This is
applicable:

"Unfortunately, today's reality is that only thoughtful experts can
write explicitly concurrent programs that are correct and efficient.
This is because today's programming models for concurrency are subtle,
intricate, and fraught with pitfalls that easily (and frequently)
result in unforeseen races (i.e., program corruption) deadlocks (i.e.,
program lockup) and performance cliffs (e.g., priority inversion,
convoying, and sometimes complete loss of parallelism and/or even
worse performance than a single-threaded program). And even when a
correct and efficient concurrent program is written, it takes great
care to maintain — it's usually brittle and difficult to maintain
correctly because current programming models set a very high bar of
expertise required to reason reliably about the operation of
concurrent programs, so that apparently innocuous changes to a working
concurrent program can (and commonly do, in practice) render it
entirely or intermittently nonworking in unintended and unexpected
ways. Because getting it right and keeping it right is so difficult,
at many major software companies there is a veritable priesthood of
gurus who write and maintain the core concurrent code."
- Herb Sutter, "The Trouble with Locks",
<http://www.drdobbs.com/cpp/the-trouble-with-locks/184401930>

Although this was written in 2005 it is still relevant today. It is
understandable that Asio will be the first target of anger and
frustration when writing concurrent programs, since it is on the
"front line" so to speak. There has also been a distinct shortage of
*good* tutorials and examples for Asio. Articles or blog posts which
teach you step by step, explaining everything, and giving example code
which demonstrates best practices.

Boost.Beast is my low-level HTTP/WebSocket library which builds on Boost.Asio:
<https://github.com/boostorg/beast>

In the original release of Beast, the documentation stated "prior
understanding of Boost.Asio is required." However, field experience
has shown that users ignore that requirement and attempt to write
complex, concurrent programs as their first-time introduction to both
Beast and Asio. Based on feedback from committee members, and to serve
users better, the scope of Beast has been enlarged to include
first-time users of networking. The upcoming Boost 1.70 release
reflects this new scope and I am excited to announce some very nice
things which you can access today.

First of all, Beast documentation and examples no longer use the
"boost::asio" namespace, they the namespace alias "net::". While this
is cosmetic, it reinforces the notion when inspecting code that it is
equally applicable to Boost.Asio, Asio, and Networking TS (identifiers
which are not in the TS, such as signal_set, are still qualified with
boost::asio).

A new documentation page explains the three flavors of networking:

<https://www.boost.org/doc/libs/master/libs/beast/doc/html/beast/using_io.html>

This is also explained in my 2018 CppCon presentation:

<https://youtu.be/7FQwAjELMek?t=444>

I have added a "Networking Refresher", a complete overview of
networking from soup to nuts. No prior knowledge or understanding of
networking is required, everything is explained in detail so if you
want to learn this is the place to start. I also kept it short, but it
is loaded with hyperlinks for further learning:

<https://www.boost.org/doc/libs/master/libs/beast/doc/html/beast/using_io/asio_refresher.html>

There was a recent paper in Kona, P1269R0 ("Three Years with the
Networking TS") about difficulty of implementing timeouts. To address
this, Beast now has a stream class which implements configurable
timeouts for you, and callers no longer have to fiddle with timers
manually anymore. Everything "Just Works." It achieves the P1269R0
author's goal of having timeouts "built-in to asynchronous
operations", but in a way that fits in with the design of the TS:

<https://www.boost.org/doc/libs/master/libs/beast/doc/html/beast/using_io/timeouts.html>

I feel that this `beast::basic_stream` serves as an existence proof
that the current design of Networking TS is sound - the TS offers a
flexible toolbox which lets you build your own framework the way that
you want it, without making odd choices for you. We are still
discovering ways of leveraging it to maximum use. The
beast::websocket::stream also has built-in timeouts, but they are
enhanced to support "idle pings" (keeping client connections alive)
and everything is fully configurable:

<https://www.boost.org/doc/libs/master/libs/beast/doc/html/beast/using_websocket/timeouts.html>

All you need to do to get sensible, suggested websocket timeouts is
add one line of code after creating your stream:

ws.set_option(websocket::stream_base::timeout::suggested(
beast::role_type::server));

To address the cumbersome boilerplate of writing composed operations
(specifically the need to propagate the associated allocator and
associated executor, and to avoid invoking the completion handler from
within the initiating function when the operation would complete
immediately) Beast adds two new utility base classes, with plentiful
documentation and examples throughout:

<https://www.boost.org/doc/libs/master/libs/beast/doc/html/beast/using_io/writing_composed_operations.html>

There are two well-rounded examples which show you step by step how to
write these things in a safe way:

<https://www.boost.org/doc/libs/master/libs/beast/doc/html/beast/using_io/writing_composed_operations/echo.html>

<https://www.boost.org/doc/libs/master/libs/beast/doc/html/beast/using_io/writing_composed_operations/detect_ssl.html>

I have a big, new open source project which implements a server, that
uses the `system_context`, taking full advantage of native Windows and
Mac OS system-level execution context features. To support this use
case and industry feedback, the examples in Beast now default to being
always thread-safe. All examples use a "strand", and leverage P1322R0
("Networking TS enhancement to enable custom I/O executors"). Yes,
this paper which was approved in Kona, is now implemented in both
Boost.Beast, and Boost.Asio, including all of the Beast examples, so
if you pick up Boost 1.70 (or the master branches from github) you can
start playing with this as soon as you're done reading this message!!

<http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1322r0.html>

We have an active #beast channel in the C++ Slack
(https://slack.cpp.al) where experienced users can help, no question
is too small! I hope you will join me and the rest of the Beast and
Asio community in exploring what the very powerful Networking TS and
Asio libraries have to offer, and build something great together!

Regards

P.S. Don't forget to star the repository! <https://github.com/boostorg/beast>
_______________________________________________
Boost-users mailing list
Boost...@lists.boost.org
https://lists.boost.org/mailman/listinfo.cgi/boost-users

Olivier Tristan via Boost-users

unread,
Mar 14, 2019, 1:03:55 PM3/14/19
to Vinnie Falco via Boost-users, Olivier Tristan
Hi Vinnie,

I have followed your stuff since you were on the Juce Forum (audio
plugin developer here)

and I was wondering if you ever took a look at

https://github.com/mefyl/elle

It's a network library that use coroutine and boost asio

I was quite impressed when I saw a demo of it at a French c++ user Group.

just my 2 cents.

--
Olivier Tristan
Research & Development
www.uvi.net

james via Boost-users

unread,
Mar 14, 2019, 1:50:50 PM3/14/19
to boost...@lists.boost.org, james, boost@lists.boost.org List, C++ Library Evolution Working Group
On Thu, Mar 14, 2019 at 4:49 PM Vinnie Falco via Boost-users <boost...@lists.boost.org> wrote:
Fellow C++, Boost, and WG21 Enthusiasts, lend me your ear!

I write to inform you about exciting developments in C++ networking.


There was a recent paper in Kona, P1269R0 ("Three Years with the
Networking TS")  about difficulty of implementing timeouts. To address
this, Beast now has a stream class which implements configurable
timeouts for you, and callers no longer have to fiddle with timers
manually anymore. Everything "Just Works." It achieves the P1269R0
author's goal of having timeouts "built-in to asynchronous
operations", but in a way that fits in with the design of the TS:

<https://www.boost.org/doc/libs/master/libs/beast/doc/html/beast/using_io/timeouts.html>

I feel that this `beast::basic_stream` serves as an existence proof
that the current design of Networking TS is sound - the TS offers a
flexible toolbox which lets you build your own framework the way that
you want it, without making odd choices for you. We are still
discovering ways of leveraging it to maximum use. The
beast::websocket::stream also has built-in timeouts, but they are
enhanced to support "idle pings" (keeping client connections alive)
and everything is fully configurable:

This is excellent news. Timeouts are ASIO's biggest downfall. I'll definitely check it out.
If it's low level, and performant enough, then it paves the way for ASIO-ed connectors for things like Redis and ZeroMQ.

Vinnie Falco via Boost-users

unread,
Mar 14, 2019, 2:11:02 PM3/14/19
to james, Vinnie Falco, boost@lists.boost.org List, C++ Library Evolution Working Group, Boost users list
On Thu, Mar 14, 2019 at 10:50 AM james <dirty...@gmail.com> wrote:
> This is excellent news. Timeouts are ASIO's biggest downfall. I'll definitely check it out.
> If it's low level, and performant enough, then it paves the way for ASIO-ed connectors for things like Redis and ZeroMQ.

Thanks! And we are very happy to answer questions, feel free to open
an issue or come to the #beast Slack channel.

Regards

Vinnie Falco via Boost-users

unread,
Mar 14, 2019, 8:20:18 PM3/14/19
to Ivan Matek, Vinnie Falco, boost, C++ Library Evolution Working Group, Boost users list
On Thu, Mar 14, 2019 at 5:09 PM Ivan Matek <libb...@gmail.com> wrote:
> Quite a weird pattern, where buffer does not have member begin, end.
> Maybe a sentence or two describing the rationale and complexity would be nice.
> I know it is O(1), but it is weird that begin/end are called on pointer.

Yeah, well... that's a sore subject. First of all I did not invent
these buffer concepts, they are part of Asio and Networking TS. And
they *used* to have begin() and end(), but then the C++ Standards
Committee decided that they didn't like `const_buffers_1` and
`mutable_buffers_1`, so they got rid of them in the TS draft. Then
they realized that having `const_buffer::begin()` would be confusing.
Does it refer to the beginning of the buffer sequence, or does it
refer to the first byte of that buffer? They decided to get rid of
begin/end entirely for the buffer types and add buffer_sequence_begin
and buffer_sequence_end in its place. And this is why we can't have
nice things.

>
> std::size_t read_line
> I am tired, but is this function O(n^2)?

It starts over from the beginning of the range so there can be some
overlap of the searching, yes.

> cb += bytes_transferred; // adjust the pointer and size
> I would maybe switch to write instead of write_some to keep the code shorter, and mention write_some as another option in text.

Well the purpose of this example is to show the looping.

> [](error_code ec, std::size_t bytes_transferred)
> For learning purposes I would capture something in lambda by value and note that reference capture would be buggy.

That is something I might consider!! Remember though I"m stuck in
C++11 so no lambda capture assignment expressions.

Appreciate the feedback!

Regards

degski via Boost-users

unread,
Mar 15, 2019, 1:28:35 AM3/15/19
to boost, degski, Boost users list, C++ Library Evolution Working Group, Ivan Matek
On Fri, 15 Mar 2019 at 02:20, Vinnie Falco via Boost <bo...@lists.boost.org> wrote:
Remember though I"m stuck in C++11 so no lambda capture assignment expressions.

Forever?

degski
--
"Big boys don't cry" - Eric Stewart, Graham Gouldman

Klebsch, Mario via Boost-users

unread,
Mar 15, 2019, 4:21:03 AM3/15/19
to Osman Zakir via Boost-users, Klebsch, Mario
Hi,


Am 14.03.2019 um 17:48 schrieb Vinnie Falco via Boost-users <boost...@lists.boost.org<mailto:boost...@lists.boost.org>>:

We've had Asio for over a decade now, but there is a shortage of
experts. Some people believe this shortage is because Asio in
particular (and thus, Networking TS since they have identical
interfaces) is "difficult to use.“

When I started using boost:asio, the biggest surprise to me was to see, that boost::asio also is a great library for synchronous networking, especially for writing programs that need to support IPv4 and IPv6 or using socket options. Almost everything is easier than directly using the plain C socket API.

The library probably was named asio, because async operations were the main improvement to the classic socket API, but that name kept me from trying it earlier. :-(

And there is one think, that IMHO should be handled in the tutorial: Lots of C programmers are familiar with using select() and lots of exciting code is structured the way to use select. Boost::asio can use null_buffers to get a similar behavior as select(): Being notified when data is ready. I know, this has a runtime performance penalty compared to using real async reading, especially on windows system, but it may it easier to convert existing code to boost::asio.

In the past days, I tried to use boost::asio::coroutine for some async operation. But that approach is hardly documented and seems to have lots of pitfalls.

I am also struggling on using synchronization primitives in async code. Unfortunately, there is no async_lock in boost::mutex and there is the requirement to call unlock() on the same thread as lock(). My synchronous code used a boost::mutex to protect against changing a std collection while iterating it to perform a possibly blocking network operation on each entry. I had to create an async version of that code and gave up after some days and simply used an additional thread.

I got all my test cases working, but I was not able to make sure, that the event handler will never block when trying to lock on the collection and I was not able to make sure that unlock() is called from the same thread, that was calling lock().

So it would be nice to find some advice or tutorial on how to use synchronization primitives (mutex, condition_variable) to synchronize async event handlers and conventional threaded code.

73, Mario
--
Mario Klebsch Actia I+ME GmbH
Mario....@ime-actia.de<mailto:Mario....@ime-actia.de> Dresdenstrasse 17/18
Fon: +49 531 38 701 716 38124 Braunschweig
Fax: +49 531 38 701 88 Germany

Cristian Morales Vega via Boost-users

unread,
Mar 15, 2019, 5:45:34 AM3/15/19
to boost...@lists.boost.org, Cristian Morales Vega, boost@lists.boost.org List, C++ Library Evolution Working Group
On Thu, 14 Mar 2019 at 16:49, Vinnie Falco via Boost-users
<boost...@lists.boost.org> wrote:
> There was a recent paper in Kona, P1269R0 ("Three Years with the
> Networking TS") about difficulty of implementing timeouts. To address
> this, Beast now has a stream class which implements configurable
> timeouts for you, and callers no longer have to fiddle with timers
> manually anymore. Everything "Just Works." It achieves the P1269R0
> author's goal of having timeouts "built-in to asynchronous
> operations", but in a way that fits in with the design of the TS:
>
> <https://www.boost.org/doc/libs/master/libs/beast/doc/html/beast/using_io/timeouts.html>

I have not used the synchronous API at all. But section 3.1 of P1269R0
seems to make a good point about the lack of timeouts in synchronous
calls, doesn't it?
beast::basic_stream makes using timeouts in the async API way simpler,
but is the sync API really basically unusable because of the lack of
timeouts thing?

james via Boost-users

unread,
Mar 15, 2019, 7:14:19 AM3/15/19
to boost...@lists.boost.org, james, boost@lists.boost.org List, C++ Library Evolution Working Group
On Fri, Mar 15, 2019 at 9:45 AM Cristian Morales Vega via Boost-users <boost...@lists.boost.org> wrote:
On Thu, 14 Mar 2019 at 16:49, Vinnie Falco via Boost-users
<boost...@lists.boost.org> wrote:
> There was a recent paper in Kona, P1269R0 ("Three Years with the
> Networking TS")  about difficulty of implementing timeouts. To address
> this, Beast now has a stream class which implements configurable
> timeouts for you, and callers no longer have to fiddle with timers
> manually anymore. Everything "Just Works." It achieves the P1269R0
> author's goal of having timeouts "built-in to asynchronous
> operations", but in a way that fits in with the design of the TS:
>
> <https://www.boost.org/doc/libs/master/libs/beast/doc/html/beast/using_io/timeouts.html>

I have not used the synchronous API at all. But section 3.1 of P1269R0
seems to make a good point about the lack of timeouts in synchronous
calls, doesn't it?
beast::basic_stream makes using timeouts in the async API way simpler,
but is the sync API really basically unusable because of the lack of
timeouts thing?

Yes, for anything other than a toytown application at least.

Vinnie Falco via Boost-users

unread,
Mar 15, 2019, 8:08:22 AM3/15/19
to Cristian Morales Vega, Vinnie Falco, boost@lists.boost.org List, Boost users list
On Fri, Mar 15, 2019 at 2:45 AM Cristian Morales Vega
<cris...@samknows.com> wrote:
> I have not used the synchronous API at all. But section 3.1 of P1269R0
> seems to make a good point about the lack of timeouts in synchronous
> calls, doesn't it?
> beast::basic_stream makes using timeouts in the async API way simpler,
> but is the sync API really basically unusable because of the lack of
> timeouts thing?

Synchronous APIs are perfectly fine. Asio defines SyncReadStream and
SyncWriteStream named requirements, allowing for generic algorithms to
be implemented. Not everything is a socket (for example, a serial
port). A synchronous stream represents the reliable, in-order delivery
of bytes using functions that block, nothing more and nothing less.
For example, serial file I/O can be represented using a synchronous
stream. If the synchronous stream requirements mandated timeouts, it
would eliminate a broad set of implementations (including sockets on
some platforms).

Stian Zeljko Vrba via Boost-users

unread,
Mar 15, 2019, 10:20:08 AM3/15/19
to C++ Library Evolution Working Group, boost@lists.boost.org List, boost...@lists.boost.org, Stian Zeljko Vrba

Sigh. A few comments from real-world experience.


>  We've had Asio for over a decade now, but there is a shortage of experts. Some people believe this shortage is because Asio in

particular (and thus, Networking TS since they have identical
interfaces) is "difficult to use."
>
> I believe it is wrong to blame Asio for this.

I disagree. Recently, I've been coding parallel, including networked & asynchronous, programs in C# and Java, and the experience has been a JOY. You get threads, executors, synchronization primitives, tasks, cancellation, monadic futures and concurrent (blocking and non-blocking) data structures out of the box with the platform, plus a myriad of extensions as libraries. As for executors, you don't need to be bothered with them unless you really want to for some reason.

In the beginning the C# program had 2 bugs (premature exit and deadlock) both of which were easy to find fix. This program has now hundreds of hours of heavy usage w/o bugs. It was easy and a joy to build thanks to the platform facilities.

In the java program I'm developing now, UI must be updated from "the UI thread". It took me whole *half an hour* to figure out how to write an executor that delegates execution to the UI thread and how to continue a completed future there (the flow is asynchronous network thread -> ui thread). All that just using the official JDK documentation, no external tutorials needed.

Compare the documentation for Vertx (vertx.io) or netty (both Java toolkits for writing asynchronous reactive programs) with that of asio.


On another C++ project, I had to roll my own.. basically everything built upon thread/mutex/cv and _unfortunately_ I decided to use asio for networking and serial ports. I feel dread every time I have to visit asio code and I regret I simply didn't use native Win32 APIs with direct callbacks. There are still native bits in there because Win32 natively supports cancellation of _synchronous_ blocking operations.

Once I attempted to write an asio service, tried to understand the simple example from the documentation, and I gave up. I used a thread, blocking call and CancelSynchronousIO (and I consider myself fortunate to develop for Windows only that has it).

Asio _is_ a relatively nice wrapper around socket and serial port APIs, but that's about it, IMO. On the other hand, I could have written the same wrappers around native APIs in two days and not haul along what I consider the baggage of technical debt that is asio in the codebase.

So now I'm regrettably stuck with asio for the forseeable future for two reasons: 1) laziness (i.e., writing the said socket/serial wrappers) and 2) need for timeouts and cancellation (just as well served by thread per client and CancelSynchronousIO). Lesson learned the hard way 😞

Conclusion, if any: many people just want/need thread per client and synchronous IO for simplicity, but until asio/networking TS provide for timeouts and cancellation of synchronous requests, it's a wrong tool for those people, me included.

-- Stian


Stian Zeljko Vrba via Boost-users

unread,
Mar 15, 2019, 10:38:17 AM3/15/19
to C++ Library Evolution Working Group, boost@lists.boost.org List, boost...@lists.boost.org, Stian Zeljko Vrba

As a followup and a concrete example, here's what C++ is competing against; this piece of C# code starts an asynchronous read of a file and waits for it to complete up to some timeout value; only platform facilities are used here (i.e., no external libraries).


How does ReadAsync complete? Executor? Thread? OS-callback? Don't know, don't care, it works. I have an idea of how to accomplish the same in C++, and it's not pleasant -- worker thread, promise/future, blocking queue and CancelSynchronousIO. Cannot even use std::async because CancelSynchronousIO needs a target thread ID.


            try {
                int bytesRead = 0;
                var operationStart = DateTime.Now;
                var vt = sourceFile.ReadAsync(writeTask.Data);
                if (vt.IsCompletedSuccessfully) {
                    bytesRead = vt.Result;
                }
                else {
                    var t = vt.AsTask();
                    if (!t.Wait(State.TransferTimeoutSeconds * 1000))
                        throw new AggregateException(new TimeoutException("Reader timed out."));
                    bytesRead = t.Result;
                }
                writeTask.Data = writeTask.Data.Slice(0, bytesRead);
                var operationDuration = (DateTime.Now - operationStart);
                volumeHealthReport.ReadStatistics.UpdateBandwidth(bytesRead, operationDuration);
                return bytesRead;
            }
            catch (AggregateException e) {
                if (e.InnerException != null) writeTask.ReaderException = e.InnerException;
                else writeTask.ReaderException = e;
                volumeHealthReport.ReadStatistics.IncrementErrorCount();
                return 0;
            }



Vinnie Falco via Boost-users

unread,
Mar 15, 2019, 10:43:54 AM3/15/19
to Stian Zeljko Vrba, Vinnie Falco, boost@lists.boost.org List, boost...@lists.boost.org
On Fri, Mar 15, 2019 at 7:19 AM Stian Zeljko Vrba <vr...@quine.no> wrote:

> I believe it is wrong to blame Asio for this.


I disagree. Recently, I've been coding parallel, including networked & asynchronous, programs in C# and Java, and the experience has been a JOY. You get threads, executors, synchronization primitives, tasks, cancellation, monadic futures and concurrent (blocking and non-blocking) data structures out of the box with the platform, plus a myriad of extensions as libraries. As for executors, you don't need to be bothered with them unless you really want to for some reason.

If you were to compare POSIX or BSD sockets to C# and Java, you would say exactly the same things. Asio (like Beast) is a low-level, portable abstraction of I/O. You can BUILD "threads", "executors", "synchronization primitives", "tasks", "cancellation", "monadic futures", and "concurrent data structures" with it. Does this mean OS-level sockets are the wrong abstraction?

Of course not. The reason C# seems "ahead" of C++ is two-fold:

1. WG21 goofed up by delaying networking
2. C# is not developed through the International Standards Process

These mistakes are being fixed though, and you will see library support in C++ catch up by leaps and bounds. And when we finally get these things (built on top of Asio/Networking TS, which has proven over and over to be the correct low-level abstraction) it will be better than C#, Java, or Rust.


Compare the documentation for Vertx (vertx.io) or netty (both Java toolkits for writing asynchronous reactive programs) with that of asio.

Yes I agree, there is a lack of documentation and especially tutorials for beginners (which I am trying to fix). This has nothing to do with whether Asio is the right portable, low-level abstraction (it is) but the lack of guidance from the author could lead you to believe incorrect things about the lib.

Once I attempted to write an asio service, tried to understand the simple example from the documentation, and I gave up. I used a thread, blocking call and CancelSynchronousIO (and I consider myself fortunate to develop for Windows only that has it).

The documentation on services is particularly scant. There is no explanation of what they are for, how to use them, best practices, or even "Frequently Asked Questions." I was able to figure it out though, but I am able to focus all of my time on it.
 
Asio _is_ a relatively nice wrapper around socket and serial port APIs, but that's about it

Yes now you're getting close to an accurate description. More correct would be to say that Asio provides robust abstractions of buffers, dynamic buffers, synchronous I/O, and asynchronous I/O. Networking is a subset of that (but not the only part, see signals and serial ports, and soon file I/O).
 
IMO. On the other hand, I could have written the same wrappers around native APIs in two days and not haul along what I consider the baggage of technical debt that is asio in the codebase.

There is no API technical debt. That is to say, that the interfaces are modern and up-to-date. You could argue that particular implementations such as Boost.Asio have extra code to provide C++03 compatibility, but this has nothing to do with the soundness of the design. As these interfaces are part of a TS, there will be implementations in gcc and clang appearing shortly (if not already so). These will be written from scratch so there will be no support for older C++.
 
Conclusion, if any: many people just want/need thread per client and synchronous IO for simplicity, but until asio/networking TS provide for timeouts and cancellation of synchronous requests, it's a wrong tool for those people, me included.

If you define

struct sync_socket
{
  net::io_context ioc_;
  net::ip::tcp::socket_;
  net::steady_timer timer_;
  ...
  template<class Buffers>
  std::size_t write_some (Buffers const& b);
};

You can easily implement timeouts in `write_some` thusly:

template<class Buffers>
std::size_t
sync_socket::
write_some (Buffers const& b, error_code& ec)
{
  std::size_t n;
  timer_.expires_after(seconds(30));
  timer_.async_wait(
    [&](error_code ec)
    {
      socket_.cancel(ec):
    });
  socket_.async_write_some(b,
    [&](error_code ec_, std::size_t n_)
    {
      ec = ec_; n = n_;
    });
    ioc_.run();
    return n;
}

Now, you can use `sync_socket` with all the usual sync write operations like `net::write`, and get timeouts.

Thanks


Vinnie Falco via Boost-users

unread,
Mar 15, 2019, 10:46:41 AM3/15/19
to Stian Zeljko Vrba, Vinnie Falco, boost@lists.boost.org List, boost...@lists.boost.org
On Fri, Mar 15, 2019 at 7:38 AM Stian Zeljko Vrba <vr...@quine.no> wrote:
> I have an idea of how to accomplish the same in C++, and
> it's not pleasant -- worker thread, promise/future, blocking
> queue and CancelSynchronousIO. Cannot even use
> std::async because CancelSynchronousIO needs a
> target thread ID.

Yes, yes! I see now...your ideas on how to implement it in C++
convince me more than anything that the documentation is the problem.
There's no need for any of that stuff, the code you provided could be
implemented in C++ using asio without too much fuss, and there are
actually several ways to do it all of which are succinct and will work
wonderfully.

Cristian Morales Vega via Boost-users

unread,
Mar 15, 2019, 10:58:21 AM3/15/19
to boost...@lists.boost.org, Cristian Morales Vega
On Fri, 15 Mar 2019 at 14:44, Vinnie Falco via Boost-users
<boost...@lists.boost.org> wrote:
> The documentation on services is particularly scant. There is no explanation of what they are for, how to use them, best practices, or even "Frequently Asked Questions." I was able to figure it out though, but I am able to focus all of my time on it.

How much time I did lose looking at "services" when I actually only
needed a "composed operation"... (at that point the ASIO docs had one
example of a service, but none of a "composed operation"; now it has
of both, so it's improving).
When you explain it it actually sounds obvious... and I feel silly for
not seeing it. You do that a lot to me.

Stian Zeljko Vrba via Boost-users

unread,
Mar 15, 2019, 11:50:19 AM3/15/19
to Vinnie Falco, Stian Zeljko Vrba, boost@lists.boost.org List, boost...@lists.boost.org

> I see now...your ideas on how to implement it in C++

convince me more than anything that the documentation is the problem.

The documentation definitely is a problem, but consider the following trade-offs:

- It took me half an hour to write the function in C# based on simple platform-provided and easily discoverable abstractions (IntelliSense lists ReadAsync just by side with Read; from there on it's easy to discover the remaining bits and pieces, and there's not much more to understand for the simplest use cases like that one).

- It'd probably take me 2-3 hours to implement the said thread/queue algorithm. It'd be boring, "obviously correct" code, built on simple concurrency primitives, understandable and maintainable by others. It'd also have simple failure modes.

- It'd take me ?? hours to understand the myriad of underlying asio concepts and their interplay, ?? hours to implement it, ?? hours to test it suitably (or become convinced of correctness in another way) and it'd have more complex failure modes (as anything else asynchronous). Also it would probably be non-understandable "black magic" to others who haven't spent at least ?? hours understanding the same bits of asio as well.

I have taken a look at your tutorial on writing composed operations -- which is very well written -- but I already see that the time required to read and understand it is longer than the time I used to implement the pasted C# snippet. (Yes, it demonstrates a different use-case, but the point stands I believe.)

I'm not disputing that asio is built on solid abstractions and concepts, what I'm trying to say is that "something" should exist that would allow me to write the same functionality in 30 minutes in C++ the only prior knowledge being "there exists primitive for asynchronously reading from a file" (the same prior knowledge in the case of C#).

Whether that "something" is "documentation for dummies", a "book of recipes", high-level utility library, … ?, I do not know.

I only know that I'm 2-3X more productive in Java/C# than in C++ (collusion of different factors; another story), and the gap is increasing. Working code needs to be delivered, customers are waiting and there's only so much time one can dedicate to studying arcane details of solidly designed but on the first sight impenetrable libraries.

-- Stian


From: Vinnie Falco <vinnie...@gmail.com>
Sent: Friday, March 15, 2019 3:46:07 PM
To: Stian Zeljko Vrba
Cc: bo...@lists.boost.org List; boost...@lists.boost.org
Subject: Re: [Boost-users] Networking TS + Beast, NEW Tutorials, Read this to learn std::net !!!
 

Damian Jarek via Boost-users

unread,
Mar 15, 2019, 2:09:06 PM3/15/19
to boost...@lists.boost.org, Damian Jarek
I think you largely underestimate how many (often conflicting) requirements and user expectations a high-quality C++ library has to deal with. While efficiency in the C# world is no doubt important, it's worth remembering that a high-quality C++ library needs to be precisely specified and be very specific with its requirements and guarantees. This is why there's so many concepts required to grasp - ASIO has to introduce the necessary vocabulary to be able to provide an exact specification. Few, if any, C# programmers need to worry where a library gets their memory from or whether said library has customization points that allow the user to plug any homegrown async model they use in their project into the library (which is why ASIO has `async_result` and allows you to customize memory allocations via allocators where applicable). Additionally, judging by the API you mention, few C# users have a need to do efficient scatter-gather using non-contigous buffers. Remember, C++ is often used where no other high-level language has gone before.

I could go on and put features from both ASIO and the C# async library side-by-side, but I think you get the picture. C++ libraries aren't complex because library developers like to masturbate while watching listings of their code - the complexity is there for a purpose (of course, sometimes it's not justifiable, mistakes happen). Library authors in higher-level languages can often make a lot of arbitrary decisions in a library, likely, because their users don't mind for the most part. In C++, a component that makes arbitrary decisions without any way to change them or to customize, most likely doesn't get used (anyone remember std::async() ?).

Stian Zeljko Vrba via Boost-users

unread,
Mar 15, 2019, 2:58:26 PM3/15/19
to Damian Jarek, boost...@lists.boost.org, Stian Zeljko Vrba

Remember, C++ is often used where no other high-level language has gone before. 


I'm well aware of that. However, how is that an argument for also not providing user-friendly, "instant productivity" high-level wrappers? By not doing that, developers having simple needs with reasonable [1] defaults are doomed to chase the rabbit-hole of complex specifications and reinvent the wheel again and again. Countless hours of programmer productivity wasted.


[1] Yes, what is reasonable? Look towards C# or Java. The wheel has already been invented.


Also, when it's easier (at least to me) to grasp raw Win32/Linux APIs than to study asio concepts and how they fit together, then the whole purpose of the standard library is defeated. Because: given an option of A: use time to learn concepts valid in C++ world only; option B: use (less) time to learn and use general OS mechanisms and concepts.. I know which route I'm going to choose and which route gives more long-term and more reusable knowledge. And probably a faster way towards working code, which is what matters in the end.


-- Stian


From: Damian Jarek <damian....@gmail.com>
Sent: Friday, March 15, 2019 7:08:32 PM
To: boost...@lists.boost.org
Cc: Vinnie Falco; Stian Zeljko Vrba

Vinnie Falco via Boost-users

unread,
Mar 15, 2019, 3:01:22 PM3/15/19
to Stian Zeljko Vrba, Vinnie Falco, boost...@lists.boost.org
On Fri, Mar 15, 2019 at 11:58 AM Stian Zeljko Vrba <vr...@quine.no> wrote:
> However, how is that an argument for also not providing user-friendly,
> "instant productivity" high-level wrappers? By not doing that, developers
> having simple needs with reasonable [1] defaults are doomed to chase
> the rabbit-hole of complex specifications and reinvent the wheel again
> and again. Countless hours of programmer productivity wasted.

So your complaint is not that Asio is bad, but that the author stopped
when he should have kept going and writing more code? Nothing stops
you or anyone else from supplying that missing code. As I have done
with Beast.

Niall Douglas via Boost-users

unread,
Mar 15, 2019, 3:19:00 PM3/15/19
to boost...@lists.boost.org, Niall Douglas
>> However, how is that an argument for also not providing user-friendly,
>> "instant productivity" high-level wrappers? By not doing that, developers
>> having simple needs with reasonable [1] defaults are doomed to chase
>> the rabbit-hole of complex specifications and reinvent the wheel again
>> and again. Countless hours of programmer productivity wasted.
>
> So your complaint is not that Asio is bad, but that the author stopped
> when he should have kept going and writing more code? Nothing stops
> you or anyone else from supplying that missing code. As I have done
> with Beast.

That's not how I read the OP's point. He seemed to me to be pointing out
that .NET APIs provide a stupid-simple API on top of lots of complexity
which itself sits on top of the Win32 winsock API.

And that I find a very fair criticism of the Networking TS, and one
shared by a ton of people on WG21. Networking ought to be some
stupid-simple coroutinised Ranges i/o API on the top. Then stuff like
strands, i/o contexts, completion tokens et al in a distinct, held
separate, API layer that you never see from the stupid simple API layer,
unless you ask. And then very low level almost-raw-sockets in a third,
distinct, held separate API at the bottom, that you ought to never see
unless you really have to.

That's the ideal in a lot of people's opinion, but nobody has the time
to do it right. So we standardise what's common practice, not what
people would prefer common practice ought to be. And that's entirely
right and proper in my book. Standards ought to be about existing
practice not about innovation, and this is one reason I find the current
trajectory of one half of the Networking TS into pure innovation land
(i.e. Executors, which don't exist anywhere yet in the proposed form)
worrying.

Me personally, I'd really like to see the bottom level part of
Networking minus all the concurrency stuff standardised separately as
soon as possible. We understand that part well. But, up to the TS
editors and champions in the end, and they've not decided to do that.

Niall

Vinnie Falco via Boost-users

unread,
Mar 15, 2019, 3:28:39 PM3/15/19
to Boost users list, Vinnie Falco
On Fri, Mar 15, 2019 at 12:19 PM Niall Douglas via Boost-users
<boost...@lists.boost.org> wrote:
> That's not how I read the OP's point. He seemed to me to be pointing out
> that .NET APIs provide a stupid-simple API on top of lots of complexity
> which itself sits on top of the Win32 winsock API.

Well, I think you read it incorrectly.

> And that I find a very fair criticism of the Networking TS

You're doing the same thing that the OP did, which is blaming
Networking TS for not doing enough. Let me see if I can explain it
"stupid-simple" for you:

We have this lower layer N (which is Networking TS) but users want SS
(stupid-simple high level interface). SS can be implemented in terms
of N, and you criticize Networking TS because it is N and not SS. It
sounds like I have perfectly characterized the point of both the OP
and yourself. I agree that we need SS but that doesn't mean we should
not have N. Then there's B (for Beast) which uses N, and can be used
to write SS but that's a whole different discussion :)

Here's a diagram to make it easy:

SS Stupid/Simple <--- You want this
B Beast <--- We have this now
N Networking TS <-- We've had this

Please show me on the diagram why the availability of N and/or B are
obstacles to implement SS?

Thanks

Niall Douglas via Boost-users

unread,
Mar 15, 2019, 4:45:32 PM3/15/19
to Boost users list, Niall Douglas
>> And that I find a very fair criticism of the Networking TS
>
> You're doing the same thing that the OP did, which is blaming
> Networking TS for not doing enough.

That would be a mischaracterisation. What I said is that there is an
ideal design which lots of people would like if infinite development
resources were available. The kind of resourcing which .NET had, for
example. But we don't and didn't have that, so we don't get the
stupid-simple API part. We stop short in the complex intermediate API,
with the layers all smooshed together and indistinct. And not separated
cleanly.

> Please show me on the diagram why the availability of N and/or B are
> obstacles to implement SS?

Beast is an extreme example of a design wholly dependent on that of an
external library. As ASIO changes, you'll have to spent a lot of time
keeping up using resources which you'd prefer to invest elsewhere. This
is a big reason why people don't choose Boost, and instead do poor man's
local clones of Boost facilities. It guarantees no coupling on
externally moving targets.

For the same reason, it takes a lot of resources to build stupid simple
high level APIs on top of shifting lower level APIs. I'm not sure it can
be done by people unless full time employed to do so. And that's been
historically very hard in C++, only a very few parts of the standard
library were developed by people employed to solely do that and nothing
else.

So tldr, it's not an engineering problem, it's a resourcing problem,
including the enormous resourcing requirement to build a consensus at
WG21 and get it through plenary. Look at the vast resourcing Ranges or
Coroutines sucked down, for example. High level stupid simple APIs are
hideously expensive to standardise, even for a big multinational
corporation like Microsoft (which largely sponsored both).

Niall

Miguel Ojeda via Boost-users

unread,
Mar 16, 2019, 1:33:41 AM3/16/19
to boost...@lists.boost.org, Miguel Ojeda
On Fri, Mar 15, 2019 at 8:19 PM Niall Douglas via Boost-users
<boost...@lists.boost.org> wrote:
>
> Me personally, I'd really like to see the bottom level part of
> Networking minus all the concurrency stuff standardised separately as
> soon as possible. We understand that part well. But, up to the TS
> editors and champions in the end, and they've not decided to do that.

I think a lot of people, myself included, would have been happy with
just having access to a low-level standard sockets API; and then building on top
of it later on.

Cheers,
Miguel

Stian Zeljko Vrba via Boost-users

unread,
Mar 16, 2019, 3:18:20 AM3/16/19
to Vinnie Falco, Damian Jarek, Stian Zeljko Vrba, boost...@lists.boost.org

> Nothing stops you or anyone else from supplying that missing code. 


?! As I explained in the previous mail, (lack of) TIME stops me. I'm an "ordinary programmer" who *needs* networking/serial/async, but I don't need ridiculously high performance, am not networking expert and have no desire to become one. I have even less desire to spend 5X or more time developing software that will have unnecessarily high performance (!) compared to 1X development effort for "satisfactory performance" (i.e., "it works for the use case"). And I believe that I'm not alone there.


> That's not how I read the OP's point. He seemed to me to be pointing out that .NET APIs provide a stupid-simple API on top of lots of complexity which itself sits on top of the Win32 winsock API.


That's the correct interpretation.


> Networking ought to be some stupid-simple coroutinised Ranges i/o API on the top. […]


This.


-- Stian


Dmitrij V via Boost-users

unread,
Mar 16, 2019, 8:22:02 AM3/16/19
to boost...@lists.boost.org, Dmitrij V
Networking TS is great and wished (by me anyway) feature.
Though I have no full picture of whole design, I need/like it,
and I have chance to dig into it in the future.

The current TS is current progress only, and it will be simplificated
for understanding I think, but for that needs some time.

[my shorten history of learning the CPP (and I am not alone I thinking)]
0) after reading few pages of Stroustrup's C++ book: hmmm, it looks cool !
1) acquaintance to STL: that is magic !
2) acquaintance to template programming: wtf ? I have cognitive dissonance !
3) few weeks later: I done it ! I can do it ! :)
4) after reading few examples of the boost libraries: hmmm, it looks cool !
5) ...
[/end history]

To Vinnie and other devs: thanks a lot for your job !

--
the best regards

Niall Douglas via Boost-users

unread,
Mar 16, 2019, 6:05:50 PM3/16/19
to boost...@lists.boost.org, Niall Douglas
>> Networking ought to be some stupid-simple coroutinised Ranges i/o API
> on the top. […]
>
> This.

We *may* get this, if everything works out.

Eric Niebler has a fairly complete concept of what a high level Ranges
i/o ought to look like.

Dalton Woodard is working on a generic mechanism for Ranges i/o to
discover any low level scatter-gather i/o implementation, such that
Ranges can "just work" with whatever you feed it.

Elias Kosunen is working on an iostreams << replacement matching the >>
replacement which is fmt, just standardised into C++ 20.

Zach Laine and others are working on Unicode string support.

I'm working on a generic low level i/o library API, and have just
internally distributed the first draft of an enhanced C++ memory and
object model which has first class support for exchanging
representations of objects between multiple C++ programs. I'll be
releasing draft 2 to SG12 next week, I'll be speaking on the topic at
ACCU in April followed by attending WG14 in May, all building towards
generating a head of steam for progress within WG21 over
Cologne-Belfast-Prague-Bulgaria.

We'll see how things go.

Niall

Emil Dotchevski via Boost-users

unread,
Mar 16, 2019, 6:37:53 PM3/16/19
to boost...@lists.boost.org, Emil Dotchevski
On Sat, Mar 16, 2019 at 3:05 PM Niall Douglas via Boost-users <boost...@lists.boost.org> wrote:
>
> >> Networking ought to be some stupid-simple coroutinised Ranges i/o API
> > on the top. […]
> >
> > This.
>
> We *may* get this, if everything works out.
>
> Eric Niebler has a fairly complete concept of what a high level Ranges
> i/o ought to look like.
>
> Dalton Woodard is working on a generic mechanism for Ranges i/o to
> discover any low level scatter-gather i/o implementation, such that
> Ranges can "just work" with whatever you feed it.
>
> Elias Kosunen is working on an iostreams << replacement matching the >>
> replacement which is fmt, just standardised into C++ 20.
>
> Zach Laine and others are working on Unicode string support.
>
> I'm working on a generic low level i/o library API, and have just
> internally distributed the first draft of an enhanced C++ memory and
> object model which has first class support for exchanging
> representations of objects between multiple C++ programs. I'll be
> releasing draft 2 to SG12 next week, I'll be speaking on the topic at
> ACCU in April followed by attending WG14 in May, all building towards
> generating a head of steam for progress within WG21 over
> Cologne-Belfast-Prague-Bulgaria.

I don't see how it is a good thing for things that haven't been adopted to make it straight into the standard. What's wrong with publishing libraries, then standardizing the ones that are already de-facto standard? Github makes things super easy, publish stuff, and in a few years we know what's what and then standardization is a simple nod from the committee, reflecting the reality of what's already used in practice.

Robert Ramey via Boost-users

unread,
Mar 16, 2019, 7:21:23 PM3/16/19
to boost...@lists.boost.org, Robert Ramey

+1

Lot's people are saying this. But no one is listening.

Robert Ramey

Niall Douglas via Boost-users

unread,
Mar 16, 2019, 7:55:30 PM3/16/19
to boost...@lists.boost.org, Niall Douglas
> I don't see how it is a good thing for things that haven't been adopted
> to make it straight into the standard. What's wrong with publishing
> libraries, then standardizing the ones that are already de-facto
> standard? Github makes things super easy, publish stuff, and in a few
> years we know what's what and then standardization is a simple nod from
> the committee, reflecting the reality of what's already used in practice.

I don't know where you're getting this from.

Ranges has multiple implementations, and has been on github for years.

Dalton's been putting together his framework in public on github,
seeking to bridge LLFIO/ASIO/etc with plenty of stakeholder feedback.

Elias has had his library on github for yonks now with plenty of users.
It's not as old as fmt, true, it was designed to do the inverse of fmt
in a similar way.

Zach has had his Unicode library on github for years now, indeed it's
even in Boost format with a fairly complete set of Boost format docs.

LLFIO has been in public view since 2013, underwent a review here in
2015, was completely rearchitected based on that feedback and has since
gained a good few number of hardcore users.


Now, I'll grant you that none of these are ASIO-type popular libraries.
But it's not like they lack implementation and userbase experience,
either. Most of these are multi-year old codebases with real world users
using them in production, and giving ample feedback rounding off the
rough edges over time.


I'll put this another way: there are plenty of standard library
proposals before the committee with no reference implementation library
whatsoever even attempted. There are lots more where the reference
library was clearly thrown together so there was one at all, and nobody
actually uses the proposed library in production.

Nobody can say that about any of the libraries above, bar perhaps
Dalton's, and that's only because he's implementing a recently begun
feature discovery bridge between Ranges i/o and everything else. I would
agree that there is insufficient user experience of these libraries yes.
They could do with more. But I'd also argue they're in the top 5% of
standard library enhancements being currently proposed for
standardisation in terms of real world use experience. They're good,
relative to what else is being proposed. We live in the world we are in.

Emil Dotchevski via Boost-users

unread,
Mar 16, 2019, 8:42:40 PM3/16/19
to boost...@lists.boost.org, Emil Dotchevski
On Sat, Mar 16, 2019 at 4:55 PM Niall Douglas via Boost-users <boost...@lists.boost.org> wrote:
>
> > I don't see how it is a good thing for things that haven't been adopted
> > to make it straight into the standard. What's wrong with publishing
> > libraries, then standardizing the ones that are already de-facto
> > standard? Github makes things super easy, publish stuff, and in a few
> > years we know what's what and then standardization is a simple nod from
> > the committee, reflecting the reality of what's already used in practice.
>
> I don't know where you're getting this from.
>
> Ranges has multiple implementations, and has been on github for years.
>
> Dalton's been putting together his framework in public on github,
> seeking to bridge LLFIO/ASIO/etc with plenty of stakeholder feedback.
>
> Elias has had his library on github for yonks now with plenty of users.
> It's not as old as fmt, true, it was designed to do the inverse of fmt
> in a similar way.
>
> Zach has had his Unicode library on github for years now, indeed it's
> even in Boost format with a fairly complete set of Boost format docs.
>
> LLFIO has been in public view since 2013, underwent a review here in
> 2015, was completely rearchitected based on that feedback and has since
> gained a good few number of hardcore users.
>
>
> Now, I'll grant you that none of these are ASIO-type popular libraries.
> But it's not like they lack implementation and userbase experience,
> either. Most of these are multi-year old codebases with real world users
> using them in production, and giving ample feedback rounding off the
> rough edges over time.

There are many libraries that pass this rather low bar. You are not saying that all such libraries qualify for standardization, are you? What, ASIO is way too good, we can't expect this sort of excellence from any other library poised to become standardized?

How about this bar: for a library to qualify for standardization, it must have retained its dominant position for at least two years without any interface changes. To argue that this is unreasonable is equivalent to stating that there is nothing wrong with changing the interface after standardization.

> I'll put this another way: there are plenty of standard library
> proposals before the committee with no reference implementation library
> whatsoever even attempted. There are lots more where the reference
> library was clearly thrown together so there was one at all, and nobody
> actually uses the proposed library in production.

Yes I know. Total lunacy.

> They're good,
> relative to what else is being proposed.

Nobody is arguing that they are not good. There is no reason to standardize every good library out there. We should only standardize the ones that have already become THE standard in their respective domain.

Jon Kalb via Boost-users

unread,
Mar 16, 2019, 9:57:13 PM3/16/19
to Boost Users, Jon Kalb
I try to avoid saying that something must be in Boost before being accepted in std, because I don’t want it to sound like a gate keeper, but there simply is no close second to the Boost libraries for exposure and user base.

I don’t want to cast aspersions on these particular libraries (particularly since I consider some of these authors to be personal friends), nor to I want to  belittle this:

On Sat, Mar 16, 2019 at 4:55 PM Niall Douglas via Boost-users <boost...@lists.boost.org> wrote:
> But it's not like they lack implementation and userbase experience,
> either. Most of these are multi-year old codebases with real world users
> using them in production, and giving ample feedback rounding off the
> rough edges over time.

But as Emil said:

There are many libraries that pass this rather low bar.

Of any individual C++ library author today, my guess is that Eric would have the best chance of attracting a large user base for his personal GitHub, but I would still consider that exposure as below the bar of what I’d like to see for a library that we are going to put into the standard (given that, once in, we’ll never be able to drop support or modify the ABI).

Even if a library is being used by a bajillion developers at MegaCorp, I’m not willing to waiver on this. All those developers are unlikely to be using the library with as diverse a set of applications and environments as will be done by Boost users.

I know that getting a library into Boost is no small task (Niall may know that better than anyone on the planet), but if it is worth putting in std then it is worth putting in Boost first. If it isn’t worth the effort to put it into Boost, then it isn’t ready to become part of the library that we have to live with forever. If there is no time to put it into Boost first, then it is definitely being rushed.

The feedback that authors receive during the review process and from being deployed to tens of thousands of users is simply unavailable any other way. The insight gained by maintaining a library over a few release cycles for use by thousands of users in thousands of diverse applications on every conceivable platform and configuration will effect the API for the better in ways that cannot be foreseen and are likely to be under-appreciated.

Put it Boost first. (Or any other library with over 100K users and on almost every platform in modern use.)

Jon


Emil Dotchevski via Boost-users

unread,
Mar 16, 2019, 10:42:33 PM3/16/19
to boost...@lists.boost.org, Emil Dotchevski
On Sat, Mar 16, 2019 at 6:57 PM Jon Kalb via Boost-users <boost...@lists.boost.org> wrote:
> Of any individual C++ library author today, my guess is that Eric would have the best chance of attracting a large user base for his personal GitHub, but I would still consider that exposure as below the bar of what I’d like to see for a library that we are going to put into the standard (given that, once in, we’ll never be able to drop support or modify the ABI).

It appears that, depending on whom you know, it might be easier to get a library in the C++ standard compared to getting it into Boost. This speaks volumes, if not about the quality of the libraries being standardized, at least about the different mindset of the people involved.

> I know that getting a library into Boost is no small task (Niall may know that better than anyone on the planet), but if it is worth putting in std then it is worth putting in Boost first.

It appears that he has learned his lesson and won't repeat that mistake. :)

Jon Kalb via Boost-users

unread,
Mar 17, 2019, 12:42:14 AM3/17/19
to Boost Users, Jon Kalb

On Mar 16, 2019, at 7:42 PM, Emil Dotchevski via Boost-users <boost...@lists.boost.org> wrote:

On Sat, Mar 16, 2019 at 6:57 PM Jon Kalb via Boost-users <boost...@lists.boost.org> wrote:
> Of any individual C++ library author today, my guess is that Eric would have the best chance of attracting a large user base for his personal GitHub, but I would still consider that exposure as below the bar of what I’d like to see for a library that we are going to put into the standard (given that, once in, we’ll never be able to drop support or modify the ABI).

It appears that, depending on whom you know, it might be easier to get a library in the C++ standard compared to getting it into Boost.

I have heard this and I’m afraid that it might be true.

This speaks volumes, if not about the quality of the libraries being standardized, at least about the different mindset of the people involved.

Agreed. I think there is a great deal of unfounded arrogance in people that think that we can design an API that we’ll be pleased to live with forever sans extensive implementation experience.

> I know that getting a library into Boost is no small task (Niall may know that better than anyone on the planet), but if it is worth putting in std then it is worth putting in Boost first.

It appears that he has learned his lesson and won't repeat that mistake. :)

I hope not. This is a “mistake” that bears repeating.

Jon


Niall Douglas via Boost-users

unread,
Mar 17, 2019, 4:19:09 AM3/17/19
to boost...@lists.boost.org, Niall Douglas
> There are many libraries that pass this rather low bar. You are not
> saying that all such libraries qualify for standardization, are you?
> What, ASIO is way too good, we can't expect this sort of excellence from
> any other library poised to become standardized?>
> How about this bar: for a library to qualify for standardization, it
> must have retained its dominant position for at least two years without
> any interface changes. To argue that this is unreasonable is equivalent
> to stating that there is nothing wrong with changing the interface after
> standardization.

I'm not unsympathetic to this viewpoint. I've often said that nobody
should be standardising libraries which the committee invents out of
thin air, yet the committee keeps doing exactly that.

But I also think that "dominant position" is very hard nowadays. Most of
the libraries which are dominant are designed around ancient C++. They
have zero chance of standardisation. There is also the hard reality that
even if your library has been stable for years, even decades, the
committee is going to force you to completely redesign it into something
totally innovative anyway. This is exactly what has happened to ASIO,
the Networking TS will be getting close to a brand new design, a whole
new API by the time its done. Or, better worded, it was redesigned by
committee through invention out of thin air.

That suggests to not go too far down the market share route first if
your end goal is standardisation. That's simply facts on the ground,
that's the playing field, and you have to play the game that is being
played.

> Nobody is arguing that they are not good. There is no reason to
> standardize every good library out there. We should only standardize the
> ones that have already become THE standard in their respective domain.

Equally, I think most would agree that iostreams needs an overhaul for
modern C++. There is a ton of inefficiency in there, and moreover
because the language lacks understanding of stuff like i/o, the
optimiser mostly gives up when faced with trivially obvious i/o
optimisation opportunities.

This is very low hanging fruit, and it is stuff WG14 are not against
also changing for C. POSIX is also keen. It just needs someone to do the
work, coordinate the various parties, and get a common proposal over the
line.

I agree that it would be far better if multinationals sponsored this
kind of deep in-out refactoring through prototype implementation. But
they see no commercial advantage. For example, Microsoft is very well
aware that Linux file i/o is up to 80x faster than Windows' now. It's
getting embarrassing the difference. But Microsoft management can't see
how closing the gap turns into extra dollars, so they won't authorise
the works needed. They take the view that the customer will adapt if
they need to. Meanwhile, all Windows users make do with awful git
performance, and much slower compile times.

That lack of corporate sponsorship of meaningful change leaves open only
the approach of change by committee invention out of thin air. Nobody
prefers this. But what else can be done? The fact WG14 and POSIX are
warm to doing committee invention in the area of i/o shows just how much
frustration with the status quo has built up.

Niall Douglas via Boost-users

unread,
Mar 17, 2019, 4:43:01 AM3/17/19
to boost...@lists.boost.org, Niall Douglas
>> It appears that, depending on whom you know, it might be easier to get
>> a library in the C++ standard compared to getting it into Boost.
>
> I have heard this and I’m afraid that it might be true.

I'd say Chris right now would probably disagree. Beman probably would
disagree, Filesystem took far longer at WG21 than anyone reasonable
would have expected, and that's after it had gone through the Boost
process multiple times. Beman told me it took him between twenty and
twenty-five years of effort, depending on how you counted it. He wasn't
sure if he would do it again, if he could have travelled back in time to
tell his younger self.

I've heard Eric in the past say it is equally hard to get a library into
Boost as into WG21, and they are both quite different processes with
different needs and requirements. And he's said on more than one
occasion that he only has enough in him to get Ranges past either Boost,
or WG21. He doesn't have enough in him to do both.

I'd echo Eric's sentiments on this completely. I don't have it in me to
ever get a fundamentals library into Boost again. Besides, I'd likely
end up getting divorced and my children no longer speaking to me. It's
not worth it, personally speaking.

>> > I know that getting a library into Boost is no small task (Niall may
>> know that better than anyone on the planet), but if it is worth
>> putting in std then it is worth putting in Boost first.
>>
>> It appears that he has learned his lesson and won't repeat that
>> mistake. :)
>
> I hope not. This is a “mistake” that bears repeating.

I can see me doing a small niche library one day. But never again for a
fundamentals library.

I would also say that the Boost review process is a poor fit for niche
libraries. There isn't a sufficient critical mass of domain experts for
a good review, it ends up becoming a popularity vote by the
inexperienced-in-that-very-specific-topic. In reviews in the past I've
been dismayed to see the review of someone I know is a domain expert in
a library being weighted equally to reviews by those who were not. But
there is little you can do about it, when a mere five people are
reviewing, there isn't the numbers to weigh one much heavier than the
others. So a library ends up passing, despite that the domain expert
found severe flaws in the proposed design.

I'm all for more libraries heading to Boost first, where Boost is a good
fit for them. Boost was great for Outcome, precisely because Outcome had
so much review feedback available. Fundamental libraries have that. But
niche libraries don't fit Boost well. For example, I don't personally
think that the Graphics proposal would fit a Boost review well. The
bikeshedding would be enormous, the topic is quite niche, and the true
correct design is probably three separate Graphics libraries, the same
way as XML processing has three entirely separate ideal ways of library
support. There also several big, well established, dominant API
libraries none of which have a snowball's chance at WG21 due to using
ancient C++, or C.

Emil Dotchevski via Boost-users

unread,
Mar 17, 2019, 7:15:53 PM3/17/19
to boost...@lists.boost.org, Emil Dotchevski
On Sun, Mar 17, 2019 at 1:43 AM Niall Douglas via Boost-users <boost...@lists.boost.org> wrote:
>
> >> It appears that, depending on whom you know, it might be easier to get
> >> a library in the C++ standard compared to getting it into Boost.
> >
> > I have heard this and I’m afraid that it might be true.
>
> I'd say Chris right now would probably disagree. Beman probably would
> disagree, Filesystem took far longer at WG21 than anyone reasonable
> would have expected, and that's after it had gone through the Boost
> process multiple times. Beman told me it took him between twenty and
> twenty-five years of effort, depending on how you counted it. He wasn't
> sure if he would do it again, if he could have travelled back in time to
> tell his younger self.

Of course WG21 could have simply accepted the library after it went through years of development and reviews, rather than trying to "fix" it. This is precisely why WG21 should not be involved in innovation and design, because then acceptance becomes a matter of opinion and politics, rather than a simple acknowledgement of an interface that is already successful.

> I'd echo Eric's sentiments on this completely. I don't have it in me to
> ever get a fundamentals library into Boost again. Besides, I'd likely
> end up getting divorced and my children no longer speaking to me. It's
> not worth it, personally speaking.

You leave out the other possibility, to leave the library out of the standard, where most libraries, including good libraries, belong.

Vinnie Falco via Boost-users

unread,
Mar 17, 2019, 7:21:26 PM3/17/19
to Ivan Matek, Vinnie Falco, boost, Boost users list
> Somebody(tm) (ASIO or Beast) maybe should make buffer that has has member fn content() that returns a range with begin and end.

Yes that is in Boost.Beast 1.70:
<https://www.boost.org/doc/libs/master/libs/beast/doc/html/beast/ref/boost__beast__buffers_range.html>

Gavin Lambert via Boost-users

unread,
Mar 17, 2019, 8:10:58 PM3/17/19
to boost...@lists.boost.org, Gavin Lambert
On 16/03/2019 03:38, Stian Zeljko Vrba wrote:
> As a followup and a concrete example, here's what C++ is competing
> against; this piece of C# code starts an asynchronous read of a file and
> waits for it to complete up to some timeout value; only platform
> facilities are used here (i.e., no external libraries).
[...]
> var vt = sourceFile.ReadAsync(writeTask.Data);
> if (vt.IsCompletedSuccessfully) {
> bytesRead = vt.Result;
> }
> else {
>                     var t = vt.AsTask();
>                     if (!t.Wait(State.TransferTimeoutSeconds * 1000))
>                         throw new AggregateException(new
> TimeoutException("Reader timed out."));

FWIW, using Task.Wait is in general not recommended. It's relatively
safe on a worker thread that is only doing one async thing (but not
always safe if there are multiple async operations). It's pretty much
never safe to call it on the UI thread.

In fact async-and-then-wait is an anti-pattern, since the code is not
actually asynchronous at all. You should either make it actually
asynchronous or use the synchronous read API instead.

(As it is, the task actually continues running even when your "timeout"
occurs, because you're not using task cancellation correctly.)

Niall Douglas via Boost-users

unread,
Mar 17, 2019, 9:19:46 PM3/17/19
to boost...@lists.boost.org, Niall Douglas
> Of course WG21 could have simply accepted the library after it went
> through years of development and reviews, rather than trying to "fix"
> it. This is precisely why WG21 should not be involved in innovation and
> design, because then acceptance becomes a matter of opinion and
> politics, rather than a simple acknowledgement of an interface that is
> already successful.

Like Boost, they declare changes which must be made before acceptance.
For some features e.g. Coroutines, it ends up being an awful lot of
discussion but ultimately very few actual changes other than naming. For
others e.g. Filesystem, probably Networking, it becomes how long is a
piece of string. Back when Gor started down the standards route for
Coroutines, I remember warning him over a burger on a park bench in
Aspen just how long a piece of string he could end up upon. He ended up
proving me wrong, I am glad to say, just seven years approx start to
finish. But it looked at the time to be a decade plus effort to reach
consensus for his proposal.

For any reasonably disruptive change, you've got to sign on to investing
a decade plus of your life to reach standards fruition. Given that we
all get maybe thirty to forty years of professional career, that's a
very big claim on your productive years.

>> I'd echo Eric's sentiments on this completely. I don't have it in me to
>> ever get a fundamentals library into Boost again. Besides, I'd likely
>> end up getting divorced and my children no longer speaking to me. It's
>> not worth it, personally speaking.
>
> You leave out the other possibility, to leave the library out of the
> standard, where most libraries, including good libraries, belong.

The same argument would then apply to Boost by this logic. I'm not sure
that I agree with that.

The usual counterargument to standardising ever more libraries generally
involves a decent centralised package ecosystem for C++, and sure, I get
that that would avoid much over-eager standardisation. However Python
has world class centralised package management (albeit with a few
forks), yet in many people's opinion continues to aggregate too much
inferior functionality into its standard library given the extremely
high quality of substitutes in its package repos. In particular, some
people feel that an inferior library gets into Python's standard
library, when a much superior alternative does not. And that's because
the inferior library had a champion, and the superior library did not.

Ultimately it comes down to committee perception of champions. If
someone is willing to champion a library into the standard, in C++ and
Python it generally tends to happen eventually given enough application
of will by the champion. The people behind the core standard essentially
assume that those motivated enough to champion a proposal for as many
years/decades as needed deserve to eventually win, irrespective of the
fundamental utility of the standard library proposal.

Contrast that with C, where the default answer to proposals for new
library features is "no, unless you can *prove* its utter necessity for
the survival of the language/ecosystem".

The former attitude invites large committees, and scalability problems
with sheer numbers. The latter attitude dissuades people such that WG14
attendance is approx 20-30 people nowadays, down from 60+ plus a decade ago.

The correct attitude is somewhere in between these two approaches. But
it's very hard to aim down the middle. I've sat in WG21 watching a
library proposal which I personally felt didn't add enough value to be
worth the committee time to pass it. But equally, it's not a bad
proposal, I personally like the proposer, and nobody else in the room
objects because they're all probably thinking the same as me. So it goes
through, and displaces time which would have have been more productively
spent elsewhere.

Personally speaking, I would prefer to have problems of scalability due
to growth and numbers rather than problems of lack of enthusiasm. So I
vote for what WG21 is doing, rather than what WG14 is doing. Ultimately
ISO SC22 (Programming languages) is 99.9% volunteer-led, so you've got
to do whatever keeps bringing in the volunteers. If that means
over-standardisation in order to keep them coming, I think that's not a
terrible tradeoff given the alternative: people just stop caring to
bother at all.

Stian Zeljko Vrba via Boost-users

unread,
Mar 18, 2019, 2:55:49 AM3/18/19
to boost...@lists.boost.org, Stian Zeljko Vrba, Gavin Lambert
Oh, I know about possible caveats of Task.Wait. It's on its own worker thread, and that thread also arranges that only one async operation is in flight. And in case of timeout, the whole (composite) operation on that file is aborted, so if the task is still hanging somewhere and waiting for completion... it doesn't matter; the whole operation will have been marked as failed by the time it's completed and the thread will have moved on to the next file.

Task is MS's weird name for a future (TaskCompletionSource being the promise part), and the language (ab)uses Task<T> return value to transform async/await into state machines. THIS -- in combination with async/await (that also includes UI) -- is the situation when most (all?) caveats of waiting on a task arise, and THAT is an anti-pattern. This is not the case in my code. (Even that "anti-pattern" can be made safe with ConfigureAwait.)

Even the official Microsoft documentation (tutorial) teaches how to use Wait: https://docs.microsoft.com/en-us/dotnet/api/system.threading.tasks.task?view=netcore-2.2 ; indeed Wait is essential for fork-join parallelism or other asynchronous computations.

As for using synchronous API: no-go. Timeout is most likely due to network disk having disappeared, which puts the thread (on Linux, possibly OSX as well) into uninterruptible sleep, so I'd have to manage my own thread pool... and then the future/thread/blocking-queue solution I hinted at becomes even more complicated.

Because of uninterruptible sleep, not even the async Task may be cancellable, so I just let it hang and let the thread pool take care of spawning a new thread if necessary (assuming that async IO completion needs a dedicated thread on the platform.)

Thanks for the input though.

-----Original Message-----
From: Boost-users <boost-use...@lists.boost.org> On Behalf Of Gavin Lambert via Boost-users
Sent: Monday, March 18, 2019 01:11
To: boost...@lists.boost.org
Cc: Gavin Lambert <bo...@mirality.co.nz>
Subject: Re: [Boost-users] Networking TS + Beast, NEW Tutorials, Read this to learn std::net !!!

Emil Dotchevski via Boost-users

unread,
Mar 18, 2019, 6:55:33 PM3/18/19
to boost...@lists.boost.org, Emil Dotchevski
On Sun, Mar 17, 2019 at 6:19 PM Niall Douglas via Boost-users <boost...@lists.boost.org> wrote:
> > Of course WG21 could have simply accepted the library after it went
> > through years of development and reviews, rather than trying to "fix"
> > it. This is precisely why WG21 should not be involved in innovation and
> > design, because then acceptance becomes a matter of opinion and
> > politics, rather than a simple acknowledgement of an interface that is
> > already successful.
>
> Like Boost, they declare changes which must be made before acceptance.

If a library is successful, popular, and its interface hasn't changed for years, it makes no sense to change it and then immediately standardize it.

> >> I'd echo Eric's sentiments on this completely. I don't have it in me to
> >> ever get a fundamentals library into Boost again. Besides, I'd likely
> >> end up getting divorced and my children no longer speaking to me. It's
> >> not worth it, personally speaking.
> >
> > You leave out the other possibility, to leave the library out of the
> > standard, where most libraries, including good libraries, belong.
>
> The same argument would then apply to Boost by this logic. I'm not sure
> that I agree with that.

It absolutely does apply to Boost. To think that it does not is equivalent to thinking that all non-Boost libraries are crap.

> The usual counterargument to standardising ever more libraries generally
> involves a decent centralised package ecosystem for C++, and sure, I get
> that that would avoid much over-eager standardisation.

That's not the argument I'm making. From this point of view, the lack of centralized package ecosystem is not an excuse.

But maybe all that needs to happen to avoid the obvious problems is slow down the process: put the library in experimental and standardize it only after/if its interface has remained unchanged for several years. Wasn't this what happened with Filesystem anyway?
Reply all
Reply to author
Forward
0 new messages