This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of SG1 status.
weakly_parallel as the default forward_progress_guaranteeSection: 33.5.8 [exec.get.fwd.progress] Status: SG1 Submitter: Lewis Baker Opened: 2025-08-25 Last modified: 2025-10-20
Priority: 1
View all issues with SG1 status.
Discussion:
The get_forward_progress_guarantee CPO is intended to allow querying a scheduler as for what sort of
forward-progress guarantee it provides. Algorithms may use this to determine whether it is safe to execute
certain operations on a given scheduler. If a scheduler does not customize this query, the query will
fall back to returning a forward-progress guarantee of weakly_parallel.
parallel by default, as this will be by far the most common kind of scheduler, i.e. a scheduler that
executes on std::thread-like execution agents and that maintains a queue of scheduled tasks.
I expect it to be common that authors of schedulers may forget to customize the
get_forward_progress_guarantee_t query and just leave it at the default. This will likely leave their
scheduler reporting a weaker guarantee than it actually provides and thus not being usable within generic
algorithms that require at least parallel forward progress.
For example, the run_loop execution context defined in 33.12.1 [exec.run.loop] does not define
its scheduler to customize the get_forward_progress_guarantee_t. This means it will report the default
value of weakly_parallel.
However, the scheduled operations will run on the thread that calls run_loop::run() and thus will
inherit its forward-progress guarantees. As this function might block and is therefore unsafe to invoke
it from a thread/agent with weakly_parallel forward progress guarantees (which should probably be
explicitly specified as having undefined-behaviour) we can safely assume that run_loop's scheduler
can provide parallel forward-progress guarantee.
It's not clear whether the current run_loop specification defaulting to its scheduler having
weakly_parallel forward progress guarantee is intentional or unintentional here. However, forgetting
to define the get_forward_progress_guarantee query on a scheduler is something I expect to be fairly common.
Schedulers that provide weakly_parallel (or in future, concurrent) forward progress guarantees require
implementations to be much more aware of the fact that these are the guarantees they are providing and
thus could be more expected to customize the get_forward_progress_guarantee query to return the
respective values.
[2025-10-20; Reflector poll. Status changed: New → SG1]
Set priority to 1 after reflector poll. Send to SG1 and LEWG.
"If there is a default, it should be the weakest possible one. If that is an unfortunate choice I’d rather prefer no default and mandate that the query gets implemented. Providing a default which is stronger than the weakest possible creates logic errors. Accidentally claiming weaker than the actual value is only a performance error."
"This is tension between the default being promising the least and the default being the most likely thing a user wants to do. Assuming the least powerful guarantees unless the user has opted in is safer. Changing this choice requires going back to LEWG or SG1."
"Plenty of reasonable schedulers are weakly parallel at best. It's the right default. If your scheduler offers better than that, you would naturally remember to customize it."
"It seems that the authors of run_loop::scheduler did not naturally remember to customize it.
It's possible the intent was that run_loop::scheduler should not offer better
than weakly_parallel forward progress, but it was not discussed in P2300.
The absence of an explicit implementation of the query could either be
intentional or an accidental omission.
Perhaps this is an indication that there should not be a default forward-progress guarantee for schedulers?"
Proposed resolution:
This wording is relative to N5014.
Modify 33.5.8 [exec.get.fwd.progress] as indicated:
-2- The name
get_forward_progress_guaranteedenotes a query object. For a subexpressionsch, letSchbedecltype((sch)). IfSchdoes not satisfyscheduler,get_forward_progress_guaranteeis ill-formed. Otherwise,get_forward_progress_guarantee(sch)is expression-equivalent to:
(2.1) —
Mandates: The type of the expression above isMANDATE-NOTHROW(AS-CONST(sch).query(get_forward_progress_guarantee))if that expression is well-formed.forward_progress_guarantee.(2.2) — Otherwise,
forward_progress_guarantee::.weakly_parallel