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.

4354. Reconsider weakly_parallel as the default forward_progress_guarantee

Section: 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.

I think we should reconsider what this default should be returning and suggest it should instead return 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.

  1. Modify 33.5.8 [exec.get.fwd.progress] as indicated:

    -2- The name get_forward_progress_guarantee denotes a query object. For a subexpression sch, let Sch be decltype((sch)). If Sch does not satisfy scheduler, get_forward_progress_guarantee is ill-formed. Otherwise, get_forward_progress_guarantee(sch) is expression-equivalent to:

    1. (2.1) — MANDATE-NOTHROW(AS-CONST(sch).query(get_forward_progress_guarantee)) if that expression is well-formed.

      Mandates: The type of the expression above is forward_progress_guarantee.

    2. (2.2) — Otherwise, forward_progress_guarantee::weakly_parallel.