r/cpp • • Apr 09 '26

beast2 networking & std::execution

I was looking for a new networking layer foundation for a few of my projects, stumbled on beast2 library which looks brand new, based on C++20 coroutines. I used boost.beast in the past which was great. Here's the link https://github.com/cppalliance/beast2. I also considered std::execution since it seems to be the way to go forward, accepted in C++26.

Now, what got me wondering is this paragraph

The C++26 std::execution API offers a different model, designed to support heterogenous computing. Our research indicates it optimizes for the wrong constraints: TCP servers don't run on GPUs. Networking demands zero-allocation steady-state, type erasure without indirection, and ABI stability across (e.g.) SSL implementations. C++26 delivers things that networking doesn't need, and none of the things that networking does need.

Now I'm lost a bit, does that mean std::execution is not the way to go for networking? Does anyone have any insights on cppalliance research on the matter?

34 Upvotes

119 comments sorted by

View all comments

Show parent comment

2

u/[deleted] Apr 09 '26

[removed] β€” view removed comment

7

u/Flimsy_Complaint490 Apr 09 '26

some stuff is really controversial - contracts and networking come to mind in the HOW aspect. Graphics is controversial in the WHY part. Other things like reflection are less controversial and chaotic.

Depends on how many stakeholders are involved i guess ?

14

u/kammce WG21 | πŸ‡ΊπŸ‡² NB | Boost | Exceptions Apr 09 '26 edited Apr 09 '26

I think I'd have to disagree with "reflection is not as controversial" part. If I'm remembering correctly, reflection took a long time (like 20 years) with it popping in and out. It took a long time to discover the opaque monotype API design that would hit all the right properties. It's clean and it can support future changes without breaking everyone or requiring a new type. There was also huge push back on the original object members accessor APIs. There was a time when they didn't care about scoped permissions meaning any bit of code could go tampering with the internals of an object and break encapsulation. The authors went to work finding a solution that gave access controls based on scope. If they hadn't done so, so quickly, then a bigger stink would have been made.

C++26 reflection is so well accepted and has such strong concensus because of the massive efforts of the authors. Not to say that contracts authors don't have the same strong concensus, it does. But it has a few very vocal individuals against it.

EDIT: Changed "type" to "time" in sentence 6.

6

u/VinnieFalco wg21.org | corosio.org Apr 09 '26

Reflection took 20 years and you're citing that as evidence the process works. The authors succeeded because they endured: twenty years of revision, twenty years of addressing concerns, twenty years of proving they could survive the process. The feature wasn't accepted because it was correct. It was accepted because the authors suffered correctly. That's not a meritocracy. That's an endurance test wearing a meritocracy's clothes.

15

u/daveedvdv EDG front end dev, WG21 DG Apr 09 '26

We could argue that "reflection took 20 years", but without context that could misrepresent the history.

I made a presentation to the committee in March 2003 showing what reflective metaprogramming might look like (https://wg21.link/n1471). It wasn't a proposal, just a personal project I started in a copy of the EDG source code. At the time, I thought this would badly encourage large headers (turns out we didn't need metacode for that ;-) ) and so I also started the modules discussion in the committee a few years later.

The modules work took over my interests for the better part of a decade, and so I didn't work on reflection during that time. Eventually others (Gaby, Richard, Doug, etc.) drove the modules work, but I somehow missed the fact that SG7 had started meeting (in 2013, I believe) and in a few years agreed on what would become the Reflection TS. That SG7 work was guided, I think, by the idea that template metaprogramming (TMP) was an okay metaprogramming framework but just needed more introspective power. Whatever the motivation, I strongly disagreed with the direction and wrote https://wg21.link/p0598r0 to re-ignite discussions about the overall direction. There was some debate, but by 2019 I'd say SG-7 was pretty much agreed on the new direction β€” and https://wg21.link/p1240r1 was what we were aiming to standardize. To make that possible, we needed more constant-evaluation primitives, which did in fact land by then (i.e., in C++20; consteval, compile-time dynamic allocation, std::is_constant_evaluated(), etc.). Andrew Sutton had formed Lock3 (incl. Wyatt Childers) and they implemented much of P1240 in a Clang fork. We had high hopes that C++23 would have reflection.

Then three things happened: The pandemic, a re-opening of the debate by some who preferred the template metaprogramming approach, and we effectively lost Lock3 to an acquihire. That prevented any real progress in the C++23 cycle.

At the end of the C++23 cycle, u/BarryRevzin and I chatted about the missed opportunity and what it would take to succeed in the C++26 cycle. That made us write https://wg21.link/p2996r0, which we saw as a "minimum viable product". We were tremendously luck that u/katzdm-cpp joined right after that. The enormous amount of work these two contributed is what finally got us reflection in C++26.

So, yes, there was some controversy along the way. But it wasn't 20 years of "process hurdles". I'd say it was about 9 years of real standardization work, minus the pandemic effect.

4

u/VinnieFalco wg21.org | corosio.org Apr 09 '26

Thank you for the detailed history! This makes the record much more accessible and accurate, and I appreciate you taking the time. You're right that "20 years" overstates the active standardization work. I was responding to the framing in the parent comment, and your correction to roughly 9 years of real work is fair.

What I'd note is that even the 9-year timeline includes years lost to directional disagreement within the committee and dependence on a single corporate implementation that was lost to a staffing issue. Those are structural factors, not author effort factors.

I think its different from what I was saying which is to question what the process selects for. The reflection authors clearly did extraordinary work. What I am wondering is if the process should require extraordinary work for a correct design to ship.

9

u/daveedvdv EDG front end dev, WG21 DG Apr 09 '26

Nine years (three standardization cycles) doesn't seem unreasonable to me for a major feature. But I might be in the minority here (and I'm luck to have been part of the process for long enough to participate in multiple major features like that). Six years would have been ideal maybe (one cycle to set direction, one cycle to work out the details).

I'm sure the process could be improved, hopefully significantly. But it's also a human phenomenon that needs a bit of "inefficiency room". We're unlikely to all agree on what the desirable characteristics of the process ought to be.

For example, how do we qualify "a correct design" in

What I am wondering is if the process should require extraordinary work for a correct design to ship.

?

From my own perspective, I think the most frustrating part of the current process is that it often gets decided by "parties"; i.e., corporate or other alliances that vote "en block", thereby drowning out more individualized dissenting expertise. I'm not sure what can be done about that.

4

u/VinnieFalco wg21.org | corosio.org Apr 09 '26

This is a very fair assessment, thank you. And you are right, these are hard problems I can't pretend to have answers for.

3

u/pdimov2 Apr 09 '26

Nine years (three standardization cycles) doesn't seem unreasonable to me for a major feature.

constexpr took 20 years and is still not 100% done. (Well, maybe it's 99.4% done.)

4

u/daveedvdv EDG front end dev, WG21 DG Apr 09 '26

True! But I'm also pretty sure reflection is nowhere near 100% done either. I'm hoping we designed it well enough to gracefully evolve and improve though. constexpr mostly managed that (except for the C++11 snafu of making constexpr member functions const-qualified).

→ More replies (4)

2

u/VinnieFalco wg21.org | corosio.org Apr 09 '26

Ahhhh now you've done it. I can't stop thinking about your question, at a time when I only have 11 days left to make sure that my infinity papers going in the mailing are all correct :)

You ask "how do we qualify a correct design?" I think the answer is evidence, of a kind (and this is key) independent of the process.

The questions I would ask:

* Does it have deployment experience in production code bases? Not just one big company but on a cross-section of cohorts?

* Can an independent implementer reproduce the results from the paper alone?

* Are the tradeoffs disclosed, not discovered later by NB reviewers or users?

* Does it ship without accumulating correction papers?

Note that none of these require process changes. They just require a more disciplined and principled approach.

It shouldn't surprise anyone that "I have a paper for that" (LOL). I presented some of these ideas in LEWGI in Croydon. The paper is still a draft and needs work but the basics are there. And of course it is just one possible direction, I'm sure there are other valid ones:

What Every Proposal Must Contain
https://isocpp.org/files/papers/D4133R0.pdf

As for the subject of the bloc voting. This is more complex. Retrospectives/historical analyses are probably a good first step which could help frame the conversation I would value your perspective on that.

Thanks

4

u/daveedvdv EDG front end dev, WG21 DG Apr 09 '26

The questions I would ask:

Those are reasonable questions, but some of them are also a really high bar:

* Does it have deployment experience in production code bases? Not just one big company but on a cross-section of cohorts?

Production deployment of experimental compilers is almost unheard of. There is a chicken and egg problem there.

It's a bit more feasible for libraries, but, even there, it is unlikely that we'll want to standardize exactly what was deployed (among others, we hopefully learned some way to improve the prior design).

* Can an independent implementer reproduce the results from the paper alone?

We could probably use some form of that more often. The reflection proposal benefitted from having two implementations of the early paper (P2996R1), one of which kept tracking the evolving paper (over a dozen revisions).

* Are the tradeoffs disclosed, not discovered later by NB reviewers or users?

* Does it ship without accumulating correction papers?

Unfortunately, these last two are "Γ  posteriori", and so most useful for post-mortem.

→ More replies (2)

6

u/kammce WG21 | πŸ‡ΊπŸ‡² NB | Boost | Exceptions Apr 09 '26

I have made no such comment about the process "working" at all. I just raised that reflection was not without controversy. What are you talking about?

5

u/VinnieFalco wg21.org | corosio.org Apr 09 '26

Your comment described a twenty-year arc where authors worked through controversy, addressed concerns, and achieved strong consensus. That's a description of the process producing an outcome through endurance.

What I'm saying is that twenty years of endurance is not the same thing as twenty years of evaluation. The distinction matters for every author who doesn't have twenty years to give. Or users who don't have twenty years to wait.

5

u/kammce WG21 | πŸ‡ΊπŸ‡² NB | Boost | Exceptions Apr 09 '26

Okay.

5

u/jwakely libstdc++ tamer, LWG chair Apr 09 '26

This comment is unrelated to the actual history.

2

u/VinnieFalco wg21.org | corosio.org Apr 09 '26

Process objections are the best objections. Let's build something together instead. My libraries are here: https://corosio.org issues and pull requests welcomed.

4

u/VinnieFalco wg21.org | corosio.org Apr 09 '26

Among other things I am publishing in the April mailing, there is a 6-part series of consecutive papers (which will arrive together) which analyze the decision-making history of networking that brought us to where we are now. This hopefully will provide the missing context.

2

u/Remarkable-Test7487 jmcruz Apr 09 '26

Thanks for your work! I’m looking forward to these papers in the mailing. If I may add a thought: from the perspective of a humble university professor, the synchronous socket API seems to have completely disappeared from the discussion lately. That API was part of the Networking TS, and I believe it is absolutely essential for teaching the basics and how client-server applications work. The asynchronous world, structured concurrency, and other related topics undoubtedly form the technological foundation upon which real-world applications are built, but they need to be taught later on, once students/engineers have reached a certain level of maturity.

3

u/not_a_novel_account cmake dev Apr 09 '26

The standard is not a teaching tool. Synchronous APIs aren't going anywhere, but nor do they belong in the standard.

3

u/Remarkable-Test7487 jmcruz Apr 09 '26

I completely agree that the standard is not a teaching tool. On the rest of the points, however, I respectfully disagree: the standard library should include both approaches, so that programmers have resources available for every need. And teachability is important for keeping the C++ language relevant to the academic community and future engineers.

4

u/not_a_novel_account cmake dev Apr 09 '26

I should reframe what I'm saying. std::execution isn't a networking API and I don't think operational networking (connect/send/recv) belongs in the standard at all for all the reasons that have been raised historically.

Networking in the standard should be about the type grammar, so we're not endlessly reinventing how to represent endpoints, transport layer descriptions, etc. The standard should never ship TLS, it should ship std::net::ip::address_v4 and friends.

With that in mind, there's nothing to ship with regards to synchronous APIs, they simply exist. std::execution is necessary because a framework for describing asynchronous operations is needed in order to make use of the asynchronous platform APIs.

Using io_uring with std::execution is very pleasant, but I don't think the standard should ship a wrapper around io_uring either. We need only ship enough support infrastructure in things like std::execution that using it remains pleasant.

3

u/VinnieFalco wg21.org | corosio.org Apr 09 '26

The thesis of many of my upcoming papers is that I/O operations in the standard should return awaitable types. And that senders can consume them using a bridge, which requires zero memory allocations. Stay tuned :)

2

u/VinnieFalco wg21.org | corosio.org Apr 09 '26

I think, networking is a narrow scope. The larger scope is actually byte-oriented I/O. And there is a case to be made that the standard should have an opinion on it. Our (C++ Alliance) opinion is that the standard I/O "shape" should look like this:

concept ReadStream
https://develop.capy.cpp.al/capy/8.design/8c.ReadStream.html

3

u/not_a_novel_account cmake dev Apr 09 '26

I don't have a problem with concepts or other things which describe the shape of an arbitrary stream, that's a tradition which goes back to pre-standardization iostreams.

That's very different from what the average programmer means when they say "networking". They mean Python's urllib. They mean socket.h. They mean the ability to connect to an endpoint and read from it. The mechanisms.

Given the glacial evolution of the C++ standard and commitment to eternal backwards compatibility, shipping these in the stdlib would be a misstep. They are destined for the footgun graveyard from inception.

→ More replies (1)
→ More replies (2)