tmp/tmpti98r3f2/{from.md → to.md}
RENAMED
|
@@ -0,0 +1,250 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
### Read-copy update (RCU) <a id="saferecl.rcu">[[saferecl.rcu]]</a>
|
| 2 |
+
|
| 3 |
+
#### General <a id="saferecl.rcu.general">[[saferecl.rcu.general]]</a>
|
| 4 |
+
|
| 5 |
+
RCU is a synchronization mechanism that can be used for linked data
|
| 6 |
+
structures that are frequently read, but seldom updated. RCU does not
|
| 7 |
+
provide mutual exclusion, but instead allows the user to schedule
|
| 8 |
+
specified actions such as deletion at some later time.
|
| 9 |
+
|
| 10 |
+
A class type `T` is *rcu-protectable* if it has exactly one base class
|
| 11 |
+
of type `rcu_obj_base<T, D>` for some `D`, and that base is public and
|
| 12 |
+
non-virtual, and it has no base classes of type `rcu_obj_base<X, Y>` for
|
| 13 |
+
any other combination `X`, `Y`. An object is rcu-protectable if it is of
|
| 14 |
+
rcu-protectable type.
|
| 15 |
+
|
| 16 |
+
An invocation of `unlock` U on an `rcu_domain dom` corresponds to an
|
| 17 |
+
invocation of `lock` L on `dom` if L is sequenced before U and either
|
| 18 |
+
|
| 19 |
+
- no other invocation of `lock` on `dom` is sequenced after L and before
|
| 20 |
+
U, or
|
| 21 |
+
- every invocation of `unlock` U2 on `dom` such that L is sequenced
|
| 22 |
+
before U2 and U2 is sequenced before U corresponds to an invocation of
|
| 23 |
+
`lock` L2 on `dom` such that L is sequenced before L2 and L2 is
|
| 24 |
+
sequenced before U2.
|
| 25 |
+
|
| 26 |
+
[*Note 1*: This pairs nested locks and unlocks on a given domain in
|
| 27 |
+
each thread. — *end note*]
|
| 28 |
+
|
| 29 |
+
A *region of RCU protection* on a domain `dom` starts with a `lock` L on
|
| 30 |
+
`dom` and ends with its corresponding `unlock` U.
|
| 31 |
+
|
| 32 |
+
Given a region of RCU protection R on a domain `dom` and given an
|
| 33 |
+
evaluation E that scheduled another evaluation F in `dom`, if E does not
|
| 34 |
+
strongly happen before the start of R, the end of R strongly happens
|
| 35 |
+
before evaluating F.
|
| 36 |
+
|
| 37 |
+
The evaluation of a scheduled evaluation is potentially concurrent with
|
| 38 |
+
any other scheduled evaluation. Each scheduled evaluation is evaluated
|
| 39 |
+
at most once.
|
| 40 |
+
|
| 41 |
+
#### Header `<rcu>` synopsis <a id="rcu.syn">[[rcu.syn]]</a>
|
| 42 |
+
|
| 43 |
+
``` cpp
|
| 44 |
+
namespace std {
|
| 45 |
+
// [saferecl.rcu.base], class template rcu_obj_base
|
| 46 |
+
template<class T, class D = default_delete<T>> class rcu_obj_base;
|
| 47 |
+
|
| 48 |
+
// [saferecl.rcu.domain], class rcu_domain
|
| 49 |
+
class rcu_domain;
|
| 50 |
+
|
| 51 |
+
// [saferecl.rcu.domain.func], non-member functions
|
| 52 |
+
rcu_domain& rcu_default_domain() noexcept;
|
| 53 |
+
void rcu_synchronize(rcu_domain& dom = rcu_default_domain()) noexcept;
|
| 54 |
+
void rcu_barrier(rcu_domain& dom = rcu_default_domain()) noexcept;
|
| 55 |
+
template<class T, class D = default_delete<T>>
|
| 56 |
+
void rcu_retire(T* p, D d = D(), rcu_domain& dom = rcu_default_domain());
|
| 57 |
+
}
|
| 58 |
+
```
|
| 59 |
+
|
| 60 |
+
#### Class template `rcu_obj_base` <a id="saferecl.rcu.base">[[saferecl.rcu.base]]</a>
|
| 61 |
+
|
| 62 |
+
Objects of type `T` to be protected by RCU inherit from a specialization
|
| 63 |
+
`rcu_obj_base<T, D>` for some `D`.
|
| 64 |
+
|
| 65 |
+
``` cpp
|
| 66 |
+
namespace std {
|
| 67 |
+
template<class T, class D = default_delete<T>>
|
| 68 |
+
class rcu_obj_base {
|
| 69 |
+
public:
|
| 70 |
+
void retire(D d = D(), rcu_domain& dom = rcu_default_domain()) noexcept;
|
| 71 |
+
protected:
|
| 72 |
+
rcu_obj_base() = default;
|
| 73 |
+
rcu_obj_base(const rcu_obj_base&) = default;
|
| 74 |
+
rcu_obj_base(rcu_obj_base&&) = default;
|
| 75 |
+
rcu_obj_base& operator=(const rcu_obj_base&) = default;
|
| 76 |
+
rcu_obj_base& operator=(rcu_obj_base&&) = default;
|
| 77 |
+
~rcu_obj_base() = default;
|
| 78 |
+
private:
|
| 79 |
+
D deleter; // exposition only
|
| 80 |
+
};
|
| 81 |
+
}
|
| 82 |
+
```
|
| 83 |
+
|
| 84 |
+
The behavior of a program that adds specializations for `rcu_obj_base`
|
| 85 |
+
is undefined.
|
| 86 |
+
|
| 87 |
+
`T` may be an incomplete type. It shall be complete before any member of
|
| 88 |
+
the resulting specialization of `rcu_obj_base` is referenced.
|
| 89 |
+
|
| 90 |
+
`D` shall be a function object type [[function.objects]] for which,
|
| 91 |
+
given a value `d` of type `D` and a value `ptr` of type `T*`, the
|
| 92 |
+
expression `d(ptr)` is valid.
|
| 93 |
+
|
| 94 |
+
`D` shall meet the requirements for *Cpp17DefaultConstructible* and
|
| 95 |
+
*Cpp17MoveAssignable*.
|
| 96 |
+
|
| 97 |
+
If `D` is trivially copyable, all specializations of
|
| 98 |
+
`rcu_obj_base<T, D>` are trivially copyable.
|
| 99 |
+
|
| 100 |
+
``` cpp
|
| 101 |
+
void retire(D d = D(), rcu_domain& dom = rcu_default_domain()) noexcept;
|
| 102 |
+
```
|
| 103 |
+
|
| 104 |
+
*Mandates:* `T` is an rcu-protectable type.
|
| 105 |
+
|
| 106 |
+
*Preconditions:* `*this` is a base class subobject of an object `x` of
|
| 107 |
+
type `T`. The member function `rcu_obj_base<T, D>::retire` was not
|
| 108 |
+
invoked on `x` before. The assignment to *deleter* does not exit via an
|
| 109 |
+
exception.
|
| 110 |
+
|
| 111 |
+
*Effects:* Evaluates *`deleter`*` = std::move(d)` and schedules the
|
| 112 |
+
evaluation of the expression *`deleter`*`( addressof(x))` in the domain
|
| 113 |
+
`dom`; the behavior is undefined if that evaluation exits via an
|
| 114 |
+
exception. May invoke scheduled evaluations in `dom`.
|
| 115 |
+
|
| 116 |
+
[*Note 1*: If such evaluations acquire resources held across any
|
| 117 |
+
invocation of `retire` on `dom`, deadlock can occur. — *end note*]
|
| 118 |
+
|
| 119 |
+
#### Class `rcu_domain` <a id="saferecl.rcu.domain">[[saferecl.rcu.domain]]</a>
|
| 120 |
+
|
| 121 |
+
##### General <a id="saferecl.rcu.domain.general">[[saferecl.rcu.domain.general]]</a>
|
| 122 |
+
|
| 123 |
+
``` cpp
|
| 124 |
+
namespace std {
|
| 125 |
+
class rcu_domain {
|
| 126 |
+
public:
|
| 127 |
+
rcu_domain(const rcu_domain&) = delete;
|
| 128 |
+
rcu_domain& operator=(const rcu_domain&) = delete;
|
| 129 |
+
|
| 130 |
+
void lock() noexcept;
|
| 131 |
+
bool try_lock() noexcept;
|
| 132 |
+
void unlock() noexcept;
|
| 133 |
+
};
|
| 134 |
+
}
|
| 135 |
+
```
|
| 136 |
+
|
| 137 |
+
This class meets the requirements of *Cpp17Lockable*
|
| 138 |
+
[[thread.req.lockable.req]] and provides regions of RCU protection.
|
| 139 |
+
|
| 140 |
+
[*Example 1*:
|
| 141 |
+
|
| 142 |
+
``` cpp
|
| 143 |
+
std::scoped_lock<rcu_domain> rlock(rcu_default_domain());
|
| 144 |
+
```
|
| 145 |
+
|
| 146 |
+
— *end example*]
|
| 147 |
+
|
| 148 |
+
The functions `lock` and `unlock` establish (possibly nested) regions of
|
| 149 |
+
RCU protection.
|
| 150 |
+
|
| 151 |
+
##### Member functions <a id="saferecl.rcu.domain.members">[[saferecl.rcu.domain.members]]</a>
|
| 152 |
+
|
| 153 |
+
``` cpp
|
| 154 |
+
void lock() noexcept;
|
| 155 |
+
```
|
| 156 |
+
|
| 157 |
+
*Effects:* Opens a region of RCU protection.
|
| 158 |
+
|
| 159 |
+
*Remarks:* Calls to `lock` do not introduce a data race [[intro.races]]
|
| 160 |
+
involving `*this`.
|
| 161 |
+
|
| 162 |
+
``` cpp
|
| 163 |
+
bool try_lock() noexcept;
|
| 164 |
+
```
|
| 165 |
+
|
| 166 |
+
*Effects:* Equivalent to `lock()`.
|
| 167 |
+
|
| 168 |
+
*Returns:* `true`.
|
| 169 |
+
|
| 170 |
+
``` cpp
|
| 171 |
+
void unlock() noexcept;
|
| 172 |
+
```
|
| 173 |
+
|
| 174 |
+
*Preconditions:* A call to `lock` that opened an unclosed region of RCU
|
| 175 |
+
protection is sequenced before the call to `unlock`.
|
| 176 |
+
|
| 177 |
+
*Effects:* Closes the unclosed region of RCU protection that was most
|
| 178 |
+
recently opened. May invoke scheduled evaluations in `*this`.
|
| 179 |
+
|
| 180 |
+
[*Note 1*: If such evaluations acquire resources held across any
|
| 181 |
+
invocation of `unlock` on `*this`, deadlock can occur. — *end note*]
|
| 182 |
+
|
| 183 |
+
*Remarks:* Calls to `unlock` do not introduce a data race involving
|
| 184 |
+
`*this`.
|
| 185 |
+
|
| 186 |
+
[*Note 2*: Evaluation of scheduled evaluations can still cause a data
|
| 187 |
+
race. — *end note*]
|
| 188 |
+
|
| 189 |
+
##### Non-member functions <a id="saferecl.rcu.domain.func">[[saferecl.rcu.domain.func]]</a>
|
| 190 |
+
|
| 191 |
+
``` cpp
|
| 192 |
+
rcu_domain& rcu_default_domain() noexcept;
|
| 193 |
+
```
|
| 194 |
+
|
| 195 |
+
*Returns:* A reference to a static-duration object of type `rcu_domain`.
|
| 196 |
+
A reference to the same object is returned every time this function is
|
| 197 |
+
called.
|
| 198 |
+
|
| 199 |
+
``` cpp
|
| 200 |
+
void rcu_synchronize(rcu_domain& dom = rcu_default_domain()) noexcept;
|
| 201 |
+
```
|
| 202 |
+
|
| 203 |
+
*Effects:* If the call to `rcu_synchronize` does not strongly happen
|
| 204 |
+
before the lock opening an RCU protection region `R` on `dom`, blocks
|
| 205 |
+
until the `unlock` closing `R` happens.
|
| 206 |
+
|
| 207 |
+
*Synchronization:* The `unlock` closing `R` strongly happens before the
|
| 208 |
+
return from `rcu_synchronize`.
|
| 209 |
+
|
| 210 |
+
``` cpp
|
| 211 |
+
void rcu_barrier(rcu_domain& dom = rcu_default_domain()) noexcept;
|
| 212 |
+
```
|
| 213 |
+
|
| 214 |
+
*Effects:* May evaluate any scheduled evaluations in `dom`. For any
|
| 215 |
+
evaluation that happens before the call to `rcu_barrier` and that
|
| 216 |
+
schedules an evaluation E in `dom`, blocks until E has been evaluated.
|
| 217 |
+
|
| 218 |
+
*Synchronization:* The evaluation of any such E strongly happens before
|
| 219 |
+
the return from `rcu_barrier`.
|
| 220 |
+
|
| 221 |
+
[*Note 3*: A call to `rcu_barrier` does not imply a call to
|
| 222 |
+
`rcu_synchronize` and vice versa. — *end note*]
|
| 223 |
+
|
| 224 |
+
``` cpp
|
| 225 |
+
template<class T, class D = default_delete<T>>
|
| 226 |
+
void rcu_retire(T* p, D d = D(), rcu_domain& dom = rcu_default_domain());
|
| 227 |
+
```
|
| 228 |
+
|
| 229 |
+
*Mandates:* `is_move_constructible_v<D>` is `true` and the expression
|
| 230 |
+
`d(p)` is well-formed.
|
| 231 |
+
|
| 232 |
+
*Preconditions:* `D` meets the *Cpp17MoveConstructible* and
|
| 233 |
+
*Cpp17Destructible* requirements.
|
| 234 |
+
|
| 235 |
+
*Effects:* May allocate memory. It is unspecified whether the memory
|
| 236 |
+
allocation is performed by invoking `operator new`. Initializes an
|
| 237 |
+
object `d1` of type `D` from `std::move(d)`. Schedules the evaluation of
|
| 238 |
+
`d1(p)` in the domain `dom`; the behavior is undefined if that
|
| 239 |
+
evaluation exits via an exception. May invoke scheduled evaluations in
|
| 240 |
+
`dom`.
|
| 241 |
+
|
| 242 |
+
[*Note 4*: If `rcu_retire` exits via an exception, no evaluation is
|
| 243 |
+
scheduled. — *end note*]
|
| 244 |
+
|
| 245 |
+
*Throws:* `bad_alloc` or any exception thrown by the initialization of
|
| 246 |
+
`d1`.
|
| 247 |
+
|
| 248 |
+
[*Note 5*: If scheduled evaluations acquire resources held across any
|
| 249 |
+
invocation of `rcu_retire` on `dom`, deadlock can occur. — *end note*]
|
| 250 |
+
|