Featured image for: Report from the virtual ISO C++ meetings in 2020 (core language).

The fall C++ meeting was held in San Diego, CA. As usual, Red Hat sent three of us to the meeting: myself from the Concurrency and Parallelism Study Group (SG1), Jason Merrill from the Core Language Working Group, and Jonathan Wakely from the Library Working Group (LEWG).

SG1 had a fairly full plate but finished the week with a bit of breathing room to spare. This article describes the major topics discussed this week in SG1.

Cooperatively interruptible joining threads, aka "jthread"

This proposal has been making the rounds for a while, most recently at the SG1/LEWG meeting adjacent CppCon in September. At that meeting, the SG1 guidance to was to remove TLS, throwing wait functions, and add support to let jthread call a callable that takes either an interrupt token as an additional first argument or does not receive any interrupt token. The proposal authors, Nico Josuttis, Herb Sutter, and Anthony Williams, brought a revised paper p0660R5 to San Diego. Nico was not present at the Bellevue meeting and wanted to discuss this further as the authors have some new experience.

It was noted that interrupting std::condition_variable waits is tricky, but that in the case of at least three library implementations, std::condition_variable_any is much easier to interrupt and can "do the right thing" where a user couldn't from within a predicate.

There was also a significant discussion about adding a callback mechanism to interrupt tokens. Some concerns were raised that there could be ABI considerations if such mechanism isn't part of C++20's interrupt token mechanism.

Later in the week, SG1 reviewed p1287R0, async use cases for interrupt_token. This was a continuation of Monday's discussion of p0660R5/p0660R6. SG1 explored the potential foot-gunnery on offer with interrupt tokens having a callback mechanism. The remainder of the discussion centered around the callback design put forward in p1287R0.

SG1 voted that "some merged version of p0660R6 and p1287R0" could be freed from the clutches of SG1, pending a wording review at a future meeting.

I have started work on an experimental version of this functionality in libstdc++.

Executors

SG1 devoted most of Monday and Tuesday to the discussion of the various executors-related papers.

First up was revision 9 of the Unified Executors Proposal for C++, aka p0443R9. After much clarifying discussion and a discussion on whether bulk_execute should be part of C++ executors, the p0443 executors with bulk_execute were also freed from the clutches of SG1, pending review at a future meeting.

In Bellevue in September, it was decided that all dependent execution features of p0443 would be split to a separate paper not targeted at C++20. As requested in Bellevue, that paper was brought in the form of p1244R0.

One obvious thing you might like to do with executors is to have them integrate with the standard library algorithms. SG1 spent some time discussing a few papers related to this topic:

  • p1019R1: Integrating Executors with Parallel Algorithms
  • p1232R0: Integrating Executors with the Standard Library Through Customization
  • p1194R0 Experience Report: Integrating Executors with Parallel Algorithms
  • D1348R0: An Executor Property for Occupancy of Execution Agents

The presentation of p1019R1 brought new material to a previous discussion of this paper and that was specifically to address a persistent question along the lines of "We have executors; why do we also need execution policies?" The discussion of p1019R1 explored this new material but no conclusions or firm direction were reached at this meeting.

P1232R0 proposes that the facilities of p0443R9 are insufficient to cover the needs of execution resources representing accelerators other than GPUs (for example, FPGAs). The paper proposes to essentially make every standard algorithm accepting an execution_policy also support n4381 (aka "ranges-style") extension points.

P1194R1 is an initial attempt to explore what would be involved in implementing an existing parallel algorithms implementation in terms of p0443R9 and p1019R1. This paper was mostly intended to be informational; I wasn't really expecting to present it. SG1 scheduled it for discussion nonetheless and that discussion in many ways was a continuation of the discussion of p1232R0. My general takeaway from the discussion is that we still don't know how to proceed toward allowing arbitrary executors to be supplied via p1019's .on() mechanism and significantly more work is needed to understand how to proceed.

Not discussed in San Diego was the integration of executors and networking, the other obvious use case. Chris Kohlhoff brought a paper revising the Networking Technical Specification to permit custom  I/O executors, p1322R0. Detlef Vollmann also brought a paper proposing merging "most" of the Networking TS into the C++ working draft. Neither of these papers was discussed this week, due to LEWG declining to advance Networking toward the C++20 IS.

Smaller papers discussed in SG1 during the San Diego meeting

  • P1258R0 Don't Make C++ Unimplementable on Small CPUs: This paper is a response to a decision at the Rapperswil meeting to make at least one lock-free atomic integer type mandatory even in freestanding C++ implementations. This is problematic for certain reasonable modern CPUs that don't provide atomic compare_exchange instructions. This paper spawned an additional evening discussion on what we should do about freestanding C++ implementations.
  • P0468R1 An Intrusive Smart Pointer: I did not attend the discussion for this paper, but there appears to have been consensus to move this toward C++23.
  • P0335R1 Context Tokens for Parallel Algorithms: This paper proposes an opt-in mechanism for customizing element access functions of a parallel algorithm by execution policy. I volunteered to prototype an implementation for libstdc++ to inform future discussion of this paper.
  • P0918R2 More simd<> Operations: This paper proposes extending the set of portably defined SIMD operations from N4755. SG1 favors the operations in P0918R2 to be included in the next shipping vehicle for simd<> operations (IS or TS) as determined by LEWG.
  • P1241R0 In Support of Merging Coroutines into C++20: I did not attend the discussion for this paper, and there are no minutes for it (was there a discussion?). See also plenary notes later on the status of coroutines.
  • P1205R0 Teleportation via co_await: The gist of the paper and the discussion of it is that a coroutine may be suspended on one execution agent and resumed on another—possibly very surprising contexts. This can have correspondingly surprising consequences (for example, TLS isn't the same once the coroutine resumes; the coroutine is resumed in a signal handler with very different constraints on what is "safe" to do, etc.). The paper proposes to clarify the coroutine wording to make this sort of usage of a coroutine implementation-defined.
  • P1288R0 Coroutine Concepts and Metafunctions: This paper proposes new concept definitions, type traits, and helpers to the standard library to support generic programming of awaitable types with coroutines. This paper provides the support/conceptual foundation for P1316R0 and P1171R0.
  • P1316R0 A when_all() Operator for Coroutines: This proposes allowing waiting on multiple co_await awaitables. The sense of the room was a "Desire to see in C++ (eventually) ..."
  • P1171R0 Synchronously Waiting on Asynchronous Operations: This proposes adding a sync_wait() operator for coroutines that allows an arbitrary awaitable to be co_awaited.
  • P1261R0 Supporting Pipelines in C++: I was not present for this paper's discussion. It seems to me that figuring out P1244R0, P1288R0, P1316R0, and P1171R0 gets C++ a long way towards a set of vocabulary types for building pipeline-like facilities.
  • P1152R0 Deprecating volatile: The title of the paper pretty much sums up its contents. Discussion and polls were mostly about guidance that the paper author, JF Bastien, was requesting for a subsequent paper revision.
  • P1202R0 Asymmetric Fences: SG1 was interested in exploring this as a direction for a future concurrency TS, subject to further wording review.

LEWG and the Networking TS

Prior to the San Diego meeting, there had been some hope that the Networking TS would be voted out of the LEWG toward the C++20 draft standard. That did not happen, as LEWG voted to target merging of the Networking TS in C++23.

This, combined with no concrete plans for how to make executors work with parallel algorithms, or what to do about std::async() in an "executors world" substantially undermine the case for executors being part of C++20 as specified in p0443, but as of now, some version of p0443 is still on track for C++20.

Coroutines and plenary

There was no consensus in Saturday's plenary to advance coroutines for inclusion in the C++20 draft. During the follow-up discussion, it was indicated that there was little likelihood that any new information could be made available by the winter meeting in Kona that would change the objection(s) to unanimous consent.

Other resources

Last updated: February 6, 2024