Files
cppdraft_translate/cppdraft/intro/progress.md
2025-10-25 03:02:53 +03:00

332 lines
12 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

[intro.progress]
# 6 Basics [[basic]](./#basic)
## 6.10 Program execution [[basic.exec]](basic.exec#intro.progress)
### 6.10.2 Multi-threaded executions and data races [[intro.multithread]](intro.multithread#intro.progress)
#### 6.10.2.3 Forward progress [intro.progress]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L6913)
The implementation may assume that any thread will eventually do one of the
following:
- [(1.1)](#1.1)
terminate,
- [(1.2)](#1.2)
invoke the function std::this_thread::yield ([[thread.thread.this]](thread.thread.this "32.4.5Namespace this_­thread")),
- [(1.3)](#1.3)
make a call to a library I/O function,
- [(1.4)](#1.4)
perform an access through a volatile glvalue,
- [(1.5)](#1.5)
perform an atomic or synchronization operation
other than an atomic modify-write operation ([[atomics.order]](atomics.order "32.5.4Order and consistency")), or
- [(1.6)](#1.6)
continue execution of a trivial infinite loop ([[stmt.iter.general]](stmt.iter.general "8.6.1General"))[.](#1.sentence-1)
[*Note [1](#note-1)*:
This is intended to allow compiler transformations
such as removal, merging, and reordering of empty loops,
even when termination cannot be proven[.](#1.sentence-2)
An affordance is made for trivial infinite loops,
which cannot be removed nor reordered[.](#1.sentence-3)
— *end note*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L6933)
Executions of atomic functions
that are either defined to be lock-free ([[atomics.flag]](atomics.flag "32.5.10Flag type and operations"))
or indicated as lock-free ([[atomics.lockfree]](atomics.lockfree "32.5.5Lock-free property"))
are [*lock-free executions*](#def:lock-free_execution "6.10.2.3Forward progress[intro.progress]")[.](#2.sentence-1)
- [(2.1)](#2.1)
If there is only one thread that is not blocked ([[defns.block]](defns.block "3.6block"))
in a standard library function,
a lock-free execution in that thread shall complete[.](#2.1.sentence-1)
[*Note [2](#note-2)*:
Concurrently executing threads
might prevent progress of a lock-free execution[.](#2.1.sentence-2)
For example,
this situation can occur
with load-locked store-conditional implementations[.](#2.1.sentence-3)
This property is sometimes termed obstruction-free[.](#2.1.sentence-4)
— *end note*]
- [(2.2)](#2.2)
When one or more lock-free executions run concurrently,
at least one should complete[.](#2.2.sentence-1)
[*Note [3](#note-3)*:
It is difficult for some implementations
to provide absolute guarantees to this effect,
since repeated and particularly inopportune interference
from other threads
could prevent forward progress,
e.g.,
by repeatedly stealing a cache line
for unrelated purposes
between load-locked and store-conditional instructions[.](#2.2.sentence-2)
For implementations that follow this recommendation and
ensure that such effects cannot indefinitely delay progress
under expected operating conditions,
such anomalies
can therefore safely be ignored by programmers[.](#2.2.sentence-3)
Outside this document,
this property is sometimes termed lock-free[.](#2.2.sentence-4)
— *end note*]
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L6974)
During the execution of a thread of execution, each of the following is termed
an [*execution step*](#def:execution_step "6.10.2.3Forward progress[intro.progress]"):
- [(3.1)](#3.1)
termination of the thread of execution,
- [(3.2)](#3.2)
performing an access through a volatile glvalue,
- [(3.3)](#3.3)
completion of a call to a library I/O function, or
- [(3.4)](#3.4)
completion of an atomic or synchronization operation
other than an atomic modify-write operation ([[atomics.order]](atomics.order "32.5.4Order and consistency"))[.](#3.sentence-1)
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L6985)
An invocation of a standard library function that blocks ([[defns.block]](defns.block "3.6block"))
is considered to continuously execute execution steps while waiting for the
condition that it blocks on to be satisfied[.](#4.sentence-1)
[*Example [1](#example-1)*:
A library I/O function that blocks until the I/O operation is complete can
be considered to continuously check whether the operation is complete[.](#4.sentence-2)
Each
such check consists of one or more execution steps, for example using
observable behavior of the abstract machine[.](#4.sentence-3)
— *end example*]
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L6996)
[*Note [4](#note-4)*:
Because of this and the preceding requirement regarding what threads of execution
have to perform eventually, it follows that no thread of execution can execute
forever without an execution step occurring[.](#5.sentence-1)
— *end note*]
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7003)
A thread of execution [*makes progress*](#def:make_progress,thread "6.10.2.3Forward progress[intro.progress]") when an execution step occurs or a
lock-free execution does not complete because there are other concurrent threads
that are not blocked in a standard library function (see above)[.](#6.sentence-1)
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7009)
For a thread of execution providing [*concurrent forward progress guarantees*](#def:concurrent_forward_progress_guarantees "6.10.2.3Forward progress[intro.progress]"),
the implementation ensures that the thread will eventually make progress for as
long as it has not terminated[.](#7.sentence-1)
[*Note [5](#note-5)*:
This applies regardless of whether or not other threads of execution (if any)
have been or are making progress[.](#7.sentence-2)
To eventually fulfill this requirement means that
this will happen in an unspecified but finite amount of time[.](#7.sentence-3)
— *end note*]
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7020)
It is implementation-defined whether the
implementation-created thread of execution that executesmain ([[basic.start.main]](basic.start.main "6.10.3.1main function")) and the threads of execution created bystd::thread ([[thread.thread.class]](thread.thread.class "32.4.3Class thread"))
or std::jthread ([[thread.jthread.class]](thread.jthread.class "32.4.4Class jthread"))
provide concurrent forward progress guarantees[.](#8.sentence-1)
General-purpose implementations should provide these guarantees[.](#8.sentence-2)
[9](#9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7030)
For a thread of execution providing [*parallel forward progress guarantees*](#def:parallel_forward_progress_guarantees "6.10.2.3Forward progress[intro.progress]"),
the implementation is not required to ensure that the thread will eventually make
progress if it has not yet executed any execution step; once this thread has
executed a step, it provides concurrent forward progress guarantees[.](#9.sentence-1)
[10](#10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7037)
[*Note [6](#note-6)*:
This does not specify a requirement for when to start this thread of execution,
which will typically be specified by the entity that creates this thread of
execution[.](#10.sentence-1)
For example, a thread of execution that provides concurrent forward
progress guarantees and executes tasks from a set of tasks in an arbitrary order,
one after the other, satisfies the requirements of parallel forward progress for
these tasks[.](#10.sentence-2)
— *end note*]
[11](#11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7047)
For a thread of execution providing [*weakly parallel forward progress
guarantees*](#def:weakly_parallel_forward_progress_guarantees "6.10.2.3Forward progress[intro.progress]"), the implementation does not ensure that the thread will eventually
make progress[.](#11.sentence-1)
[12](#12)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7053)
[*Note [7](#note-7)*:
Threads of execution providing weakly parallel forward progress guarantees cannot
be expected to make progress regardless of whether other threads make progress or
not; however, blocking with forward progress guarantee delegation, as defined below,
can be used to ensure that such threads of execution make progress eventually[.](#12.sentence-1)
— *end note*]
[13](#13)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7061)
Concurrent forward progress guarantees are stronger than parallel forward progress
guarantees, which in turn are stronger than weakly parallel forward progress
guarantees[.](#13.sentence-1)
[*Note [8](#note-8)*:
For example, some kinds of synchronization between threads of execution might only
make progress if the respective threads of execution provide parallel forward progress
guarantees, but will fail to make progress under weakly parallel guarantees[.](#13.sentence-2)
— *end note*]
[14](#14)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7071)
When a thread of execution P is specified to[*block with forward progress guarantee delegation*](#def:block_(execution),with_forward_progress_guarantee_delegation "6.10.2.3Forward progress[intro.progress]") on the completion of a set S of threads of execution,
then throughout the whole time of P being blocked on S,
the implementation shall ensure that the forward progress guarantees
provided by at least one thread of execution in S is at least as strong as P's forward progress guarantees[.](#14.sentence-1)
[*Note [9](#note-9)*:
It is unspecified which thread or threads of execution in S are chosen
and for which number of execution steps[.](#14.sentence-2)
The strengthening is not permanent and
not necessarily in place for the rest of the lifetime of the affected thread of
execution[.](#14.sentence-3)
As long as P is blocked, the implementation has to eventually
select and potentially strengthen a thread of execution in S[.](#14.sentence-4)
— *end note*]
Once a thread of execution in S terminates, it is removed from S[.](#14.sentence-5)
Once S is empty, P is unblocked[.](#14.sentence-6)
[15](#15)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7091)
[*Note [10](#note-10)*:
A thread of execution B thus can temporarily provide an effectively
stronger forward progress guarantee for a certain amount of time, due to a
second thread of execution A being blocked on it with forward
progress guarantee delegation[.](#15.sentence-1)
In turn, if B then blocks with
forward progress guarantee delegation on C, this can also temporarily
provide a stronger forward progress guarantee to C[.](#15.sentence-2)
— *end note*]
[16](#16)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7101)
[*Note [11](#note-11)*:
If all threads of execution in S finish executing (e.g., they terminate
and do not use blocking synchronization incorrectly), then P's execution
of the operation that blocks with forward progress guarantee delegation will not
result in P's progress guarantee being effectively weakened[.](#16.sentence-1)
— *end note*]
[17](#17)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7109)
[*Note [12](#note-12)*:
This does not remove any constraints regarding blocking synchronization for
threads of execution providing parallel or weakly parallel forward progress
guarantees because the implementation is not required to strengthen a particular
thread of execution whose too-weak progress guarantee is preventing overall progress[.](#17.sentence-1)
— *end note*]
[18](#18)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7117)
An implementation should ensure that the last value (in modification order)
assigned by an atomic or synchronization operation will become visible to all
other threads in a finite period of time[.](#18.sentence-1)