1. Revision History
This paper is the initial revision.
2. Introduction
Some execution environments want to make sure that specific operations are
non-blocking. These can not signal an event using the facilities of as
currently specified as it doesn’t provide operations
that are guaranteed to be non-blocking.
This became apparent in the proposal for concurrent queues C++ Concurrent Queues (P0260),
which has support for non-blocking usage.
But the non-blocking operations got a very weird interface when interfacing
with due to the lack of non-blocking signalling
to an async waiter.
In the basic operation to signal an event is to schedule
a continuation.
In practice this generally means that a operation is called
on an operation state that comes from a sender provided by a scheduler.
This proposal is independent from C++ Concurrent Queues (P0260) as the problem of signalling an event in a non-blocking way is not specific to concurrent queues.
3. Design
This paper proposes to add a operation to the
operation states that come from a scheduler
and require it to be non-blocking (and to return false if it would block).
Unfortunately it is not possible for all kind of schedulers to provide such an opertion. Schedulers that are not backed by by an execution context that maintains a work queue but run the operation right away are an example. Schedulers that enqueue the work on a different system are another example.
For this reason, this paper proposes a new concept derived from the concept. requires the operation.
While this proposal is generally independent from C++ Concurrent Queues (P0260),
we still would like to fix the weird interface in that proposal if possible.
For this the proposed wording contains a part that modifies the wording
for the queue concepts.
The idea here is to make it ill-formed if an async operation is called
for a queue that also implements and its scheduler
does not implement .
4. Proposed Wording
(Sorry, the wording is formally horribly incomplete, but I think substantially it’s fairly complete.)
4.1. Concurrency Concepts
4.1.1. Exposition-only Concurrent Op State Concept
-
The exposition-only concept concurrent-op-state defines the requirements of an operation state type ([async.ops]) that provides an operation to potentially start the operation without blocking ([defns.block]).
namespace std :: execution { template < class O > concept concurrent - op - state = operation_state < O > && requires ( O & o ) { { o . try_start () } noexcept -> bool }; } -
In the following description,
denotes a type modeling the concurrent-op-state concept andO denotes an object of typeo .O -
The expression
has the following semantics:o . try_start () -
Effects: Starts ([async.ops]) the asynchronous operation associated with
, if it can be achieved without blocking.o -
Returns:
trueif the async operation was started,falseotherwise.
-
4.1.2. Concurrent Scheduler Concept
-
The concept
defines the requirements of a scheduler type ([async.ops]) that can provide a concurrent-op-state.concurrent_scheduler namespace std :: execution { template < class S , receiver R > concept concurrent_scheduler = scheduler < S > && requires ( S && s , R && r ) { { connect ( schedule ( std :: forward < S > ( s )), std :: move ( r ) } -> concurrent - op - state ; } }
4.1.3. run_loop
-
run-loop-scheduler models
.concurrent_scheduler
4.2. Modifications for Concurrent Queues
Remove from the enumeration and the respective
return statements from , and in the concurrent-queue concept.
In the async-concurrent-queue concept add another bullet to the senders
returned by and after bullet 6:
-
If the scheduler of
does not modelr , the program is ill-formed.concurrent_scheduler