From Jason Turner

[saferecl.hp]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmpff52e0s6/{from.md → to.md} +552 -0
tmp/tmpff52e0s6/{from.md → to.md} RENAMED
@@ -0,0 +1,552 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ### Hazard pointers <a id="saferecl.hp">[[saferecl.hp]]</a>
2
+
3
+ #### General <a id="saferecl.hp.general">[[saferecl.hp.general]]</a>
4
+
5
+ A hazard pointer is a single-writer multi-reader pointer that can be
6
+ owned by at most one thread at any time. Only the owner of the hazard
7
+ pointer can set its value, while any number of threads may read its
8
+ value. The owner thread sets the value of a hazard pointer to point to
9
+ an object in order to indicate to concurrent threads—which may delete
10
+ such an object—that the object is not yet safe to delete.
11
+
12
+ A class type `T` is *hazard-protectable* if it has exactly one base
13
+ class of type `hazard_pointer_obj_base<T, D>` for some `D`, that base is
14
+ public and non-virtual, and it has no base classes of type
15
+ `hazard_pointer_obj_base<T2, D2>` for any other combination `T2`, `D2`.
16
+ An object is *hazard-protectable* if it is of hazard-protectable type.
17
+
18
+ The time span between creation and destruction of a hazard pointer h is
19
+ partitioned into a series of *protection epochs*; in each protection
20
+ epoch, h either is *associated with* a hazard-protectable object, or is
21
+ *unassociated*. Upon creation, a hazard pointer is unassociated.
22
+ Changing the association (possibly to the same object) initiates a new
23
+ protection epoch and ends the preceding one.
24
+
25
+ An object `x` of hazard-protectable type `T` is *retired* with a deleter
26
+ of type `D` when the member function
27
+ `hazard_pointer_obj_base<T, D>::retire` is invoked on `x`. Any given
28
+ object `x` shall be retired at most once.
29
+
30
+ A retired object `x` is *reclaimed* by invoking its deleter with a
31
+ pointer to `x`; the behavior is undefined if that invocation exits via
32
+ an exception.
33
+
34
+ A hazard-protectable object `x` is *possibly-reclaimable* with respect
35
+ to an evaluation A if
36
+
37
+ - `x` is not reclaimed; and
38
+ - `x` is retired in an evaluation R and A does not happen before R; and
39
+ - for all hazard pointers h and for every protection epoch E of h during
40
+ which h is associated with `x`:
41
+ - if the beginning of E happens before R, the end of E strongly
42
+ happens before A; and
43
+ - if E began by an evaluation of `try_protect` with argument `src`,
44
+ label its atomic load operation L. If there exists an atomic
45
+ modification B on `src` such that L observes a modification that is
46
+ modification-ordered before B, and B happens before `x` is retired,
47
+ the end of E strongly happens before A. \[*Note 1*: In typical use,
48
+ a store to `src` sequenced before retiring `x` will be such an
49
+ atomic operation B. — *end note*]
50
+
51
+ \[*Note 2*: The latter two conditions convey the informal notion that
52
+ a protection epoch that began before retiring `x`, as implied either
53
+ by the happens-before relation or the coherence order of some source,
54
+ delays the reclamation of `x`. — *end note*]
55
+
56
+ The number of possibly-reclaimable objects has an unspecified bound.
57
+
58
+ [*Note 3*: The bound can be a function of the number of hazard
59
+ pointers, the number of threads that retire objects, and the number of
60
+ threads that use hazard pointers. — *end note*]
61
+
62
+ [*Example 1*:
63
+
64
+ The following example shows how hazard pointers allow updates to be
65
+ carried out in the presence of concurrent readers. The object of type
66
+ `hazard_pointer` in `print_name` protects the object `*ptr` from being
67
+ reclaimed by `ptr->retire` until the end of the protection epoch.
68
+
69
+ ``` cpp
70
+ struct Name : public hazard_pointer_obj_base<Name> { /* details */ };
71
+ atomic<Name*> name;
72
+ // called often and in parallel!
73
+ void print_name() {
74
+ hazard_pointer h = make_hazard_pointer();
75
+ Name* ptr = h.protect(name); // Protection epoch starts
76
+ // ... safe to access *ptr
77
+ } // Protection epoch ends.
78
+
79
+ // called rarely, but possibly concurrently with print_name
80
+ void update_name(Name* new_name) {
81
+ Name* ptr = name.exchange(new_name);
82
+ ptr->retire();
83
+ }
84
+ ```
85
+
86
+ — *end example*]
87
+
88
+ #### Header `<hazard_pointer>` synopsis <a id="hazard.pointer.syn">[[hazard.pointer.syn]]</a>
89
+
90
+ ``` cpp
91
+ namespace std {
92
+ // [saferecl.hp.base], class template hazard_pointer_obj_base
93
+ template<class T, class D = default_delete<T>> class hazard_pointer_obj_base;
94
+
95
+ // [saferecl.hp.holder], class hazard_pointer
96
+ class hazard_pointer;
97
+
98
+ // [saferecl.hp.holder.nonmem], non-member functions
99
+ hazard_pointer make_hazard_pointer();
100
+ void swap(hazard_pointer&, hazard_pointer&) noexcept;
101
+ }
102
+ ```
103
+
104
+ #### Class template `hazard_pointer_obj_base` <a id="saferecl.hp.base">[[saferecl.hp.base]]</a>
105
+
106
+ ``` cpp
107
+ namespace std {
108
+ template<class T, class D = default_delete<T>>
109
+ class hazard_pointer_obj_base {
110
+ public:
111
+ void retire(D d = D()) noexcept;
112
+ protected:
113
+ hazard_pointer_obj_base() = default;
114
+ hazard_pointer_obj_base(const hazard_pointer_obj_base&) = default;
115
+ hazard_pointer_obj_base(hazard_pointer_obj_base&&) = default;
116
+ hazard_pointer_obj_base& operator=(const hazard_pointer_obj_base&) = default;
117
+ hazard_pointer_obj_base& operator=(hazard_pointer_obj_base&&) = default;
118
+ ~hazard_pointer_obj_base() = default;
119
+ private:
120
+ D deleter; // exposition only
121
+ };
122
+ }
123
+ ```
124
+
125
+ `D` shall be a function object type [[func.require]] for which, given a
126
+ value `d` of type `D` and a value `ptr` of type `T*`, the expression
127
+ `d(ptr)` is valid.
128
+
129
+ The behavior of a program that adds specializations for
130
+ `hazard_pointer_obj_base` is undefined.
131
+
132
+ `D` shall meet the requirements for *Cpp17DefaultConstructible* and
133
+ *Cpp17MoveAssignable*.
134
+
135
+ `T` may be an incomplete type. It shall be complete before any member of
136
+ the resulting specialization of `hazard_pointer_obj_base` is referenced.
137
+
138
+ ``` cpp
139
+ void retire(D d = D()) noexcept;
140
+ ```
141
+
142
+ *Mandates:* `T` is a hazard-protectable type.
143
+
144
+ *Preconditions:* `*this` is a base class subobject of an object `x` of
145
+ type `T`. `x` is not retired. Move-assigning `d` to `deleter` does not
146
+ exit via an exception.
147
+
148
+ *Effects:* Move-assigns `d` to `deleter`, thereby setting it as the
149
+ deleter of `x`, then retires `x`. May reclaim possibly-reclaimable
150
+ objects.
151
+
152
+ #### Class `hazard_pointer` <a id="saferecl.hp.holder">[[saferecl.hp.holder]]</a>
153
+
154
+ ##### General <a id="saferecl.hp.holder.general">[[saferecl.hp.holder.general]]</a>
155
+
156
+ ``` cpp
157
+ namespace std {
158
+ class hazard_pointer {
159
+ public:
160
+ hazard_pointer() noexcept;
161
+ hazard_pointer(hazard_pointer&&) noexcept;
162
+ hazard_pointer& operator=(hazard_pointer&&) noexcept;
163
+ ~hazard_pointer();
164
+
165
+ bool empty() const noexcept;
166
+ template<class T> T* protect(const atomic<T*>& src) noexcept;
167
+ template<class T> bool try_protect(T*& ptr, const atomic<T*>& src) noexcept;
168
+ template<class T> void reset_protection(const T* ptr) noexcept;
169
+ void reset_protection(nullptr_t = nullptr) noexcept;
170
+ void swap(hazard_pointer&) noexcept;
171
+ };
172
+ }
173
+ ```
174
+
175
+ An object of type `hazard_pointer` is either empty or *owns* a hazard
176
+ pointer. Each hazard pointer is owned by exactly one object of type
177
+ `hazard_pointer`.
178
+
179
+ [*Note 1*: An empty `hazard_pointer` object is different from a
180
+ `hazard_pointer` object that owns an unassociated hazard pointer. An
181
+ empty `hazard_pointer` object does not own any hazard
182
+ pointers. — *end note*]
183
+
184
+ ##### Constructors, destructor, and assignment <a id="saferecl.hp.holder.ctor">[[saferecl.hp.holder.ctor]]</a>
185
+
186
+ ``` cpp
187
+ hazard_pointer() noexcept;
188
+ ```
189
+
190
+ *Ensures:* `*this` is empty.
191
+
192
+ ``` cpp
193
+ hazard_pointer(hazard_pointer&& other) noexcept;
194
+ ```
195
+
196
+ *Ensures:* If `other` is empty, `*this` is empty. Otherwise, `*this`
197
+ owns the hazard pointer originally owned by `other`; `other` is empty.
198
+
199
+ ``` cpp
200
+ ~hazard_pointer();
201
+ ```
202
+
203
+ *Effects:* If `*this` is not empty, destroys the hazard pointer owned by
204
+ `*this`, thereby ending its current protection epoch.
205
+
206
+ ``` cpp
207
+ hazard_pointer& operator=(hazard_pointer&& other) noexcept;
208
+ ```
209
+
210
+ *Effects:* If `this == &other` is `true`, no effect. Otherwise, if
211
+ `*this` is not empty, destroys the hazard pointer owned by `*this`,
212
+ thereby ending its current protection epoch.
213
+
214
+ *Ensures:* If `other` was empty, `*this` is empty. Otherwise, `*this`
215
+ owns the hazard pointer originally owned by `other`. If `this != &other`
216
+ is `true`, `other` is empty.
217
+
218
+ *Returns:* `*this`.
219
+
220
+ ##### Member functions <a id="saferecl.hp.holder.mem">[[saferecl.hp.holder.mem]]</a>
221
+
222
+ ``` cpp
223
+ bool empty() const noexcept;
224
+ ```
225
+
226
+ *Returns:* `true` if and only if `*this` is empty.
227
+
228
+ ``` cpp
229
+ template<class T> T* protect(const atomic<T*>& src) noexcept;
230
+ ```
231
+
232
+ *Effects:* Equivalent to:
233
+
234
+ ``` cpp
235
+ T* ptr = src.load(memory_order::relaxed);
236
+ while (!try_protect(ptr, src)) {}
237
+ return ptr;
238
+ ```
239
+
240
+ ``` cpp
241
+ template<class T> bool try_protect(T*& ptr, const atomic<T*>& src) noexcept;
242
+ ```
243
+
244
+ *Mandates:* `T` is a hazard-protectable type.
245
+
246
+ *Preconditions:* `*this` is not empty.
247
+
248
+ *Effects:* Performs the following steps in order:
249
+
250
+ - Initializes a variable `old` of type `T*` with the value of `ptr`.
251
+ - Evaluates `reset_protection(old)`.
252
+ - Assigns the value of `src.load(memory_order::acquire)` to `ptr`.
253
+ - If `old == ptr` is `false`, evaluates `reset_protection()`.
254
+
255
+ *Returns:* `old == ptr`.
256
+
257
+ ``` cpp
258
+ template<class T> void reset_protection(const T* ptr) noexcept;
259
+ ```
260
+
261
+ *Mandates:* `T` is a hazard-protectable type.
262
+
263
+ *Preconditions:* `*this` is not empty.
264
+
265
+ *Effects:* If `ptr` is a null pointer value, invokes
266
+ `reset_protection()`. Otherwise, associates the hazard pointer owned by
267
+ `*this` with `*ptr`, thereby ending the current protection epoch.
268
+
269
+ *Complexity:* Constant.
270
+
271
+ ``` cpp
272
+ void reset_protection(nullptr_t = nullptr) noexcept;
273
+ ```
274
+
275
+ *Preconditions:* `*this` is not empty.
276
+
277
+ *Ensures:* The hazard pointer owned by `*this` is unassociated.
278
+
279
+ *Complexity:* Constant.
280
+
281
+ ``` cpp
282
+ void swap(hazard_pointer& other) noexcept;
283
+ ```
284
+
285
+ *Effects:* Swaps the hazard pointer ownership of this object with that
286
+ of `other`.
287
+
288
+ [*Note 1*: The owned hazard pointers, if any, remain unchanged during
289
+ the swap and continue to be associated with the respective objects that
290
+ they were protecting before the swap, if any. No protection epochs are
291
+ ended or initiated. — *end note*]
292
+
293
+ *Complexity:* Constant.
294
+
295
+ ##### Non-member functions <a id="saferecl.hp.holder.nonmem">[[saferecl.hp.holder.nonmem]]</a>
296
+
297
+ ``` cpp
298
+ hazard_pointer make_hazard_pointer();
299
+ ```
300
+
301
+ *Effects:* Constructs a hazard pointer.
302
+
303
+ *Returns:* A `hazard_pointer` object that owns the newly-constructed
304
+ hazard pointer.
305
+
306
+ *Throws:* May throw `bad_alloc` if memory for the hazard pointer could
307
+ not be allocated.
308
+
309
+ ``` cpp
310
+ void swap(hazard_pointer& a, hazard_pointer& b) noexcept;
311
+ ```
312
+
313
+ *Effects:* Equivalent to `a.swap(b)`.
314
+
315
+ <!-- Link reference definitions -->
316
+ [alg.min.max]: algorithms.md#alg.min.max
317
+ [alg.sorting]: algorithms.md#alg.sorting
318
+ [allocator.requirements.general]: library.md#allocator.requirements.general
319
+ [atomic.types.int.comp]: #atomic.types.int.comp
320
+ [atomic.types.pointer.comp]: #atomic.types.pointer.comp
321
+ [atomics]: #atomics
322
+ [atomics.alias]: #atomics.alias
323
+ [atomics.fences]: #atomics.fences
324
+ [atomics.flag]: #atomics.flag
325
+ [atomics.general]: #atomics.general
326
+ [atomics.lockfree]: #atomics.lockfree
327
+ [atomics.nonmembers]: #atomics.nonmembers
328
+ [atomics.order]: #atomics.order
329
+ [atomics.ref.float]: #atomics.ref.float
330
+ [atomics.ref.generic]: #atomics.ref.generic
331
+ [atomics.ref.generic.general]: #atomics.ref.generic.general
332
+ [atomics.ref.int]: #atomics.ref.int
333
+ [atomics.ref.memop]: #atomics.ref.memop
334
+ [atomics.ref.ops]: #atomics.ref.ops
335
+ [atomics.ref.pointer]: #atomics.ref.pointer
336
+ [atomics.syn]: #atomics.syn
337
+ [atomics.types.float]: #atomics.types.float
338
+ [atomics.types.generic]: #atomics.types.generic
339
+ [atomics.types.generic.general]: #atomics.types.generic.general
340
+ [atomics.types.int]: #atomics.types.int
341
+ [atomics.types.memop]: #atomics.types.memop
342
+ [atomics.types.operations]: #atomics.types.operations
343
+ [atomics.types.pointer]: #atomics.types.pointer
344
+ [atomics.wait]: #atomics.wait
345
+ [barrier.syn]: #barrier.syn
346
+ [basic.align]: basic.md#basic.align
347
+ [basic.fundamental]: basic.md#basic.fundamental
348
+ [basic.life]: basic.md#basic.life
349
+ [basic.stc.general]: basic.md#basic.stc.general
350
+ [basic.stc.thread]: basic.md#basic.stc.thread
351
+ [bitmask.types]: library.md#bitmask.types
352
+ [cfenv]: numerics.md#cfenv
353
+ [class.prop]: class.md#class.prop
354
+ [compliance]: library.md#compliance
355
+ [concept.booleantestable]: concepts.md#concept.booleantestable
356
+ [condition.variable.syn]: #condition.variable.syn
357
+ [conv.rval]: expr.md#conv.rval
358
+ [cpp17.defaultconstructible]: #cpp17.defaultconstructible
359
+ [cpp17.destructible]: #cpp17.destructible
360
+ [cpp17.lessthancomparable]: #cpp17.lessthancomparable
361
+ [cpp17.moveassignable]: #cpp17.moveassignable
362
+ [cpp17.moveconstructible]: #cpp17.moveconstructible
363
+ [defns.block]: intro.md#defns.block
364
+ [except.terminate]: except.md#except.terminate
365
+ [expr.pre]: expr.md#expr.pre
366
+ [expr.rel]: expr.md#expr.rel
367
+ [format.string.std]: text.md#format.string.std
368
+ [func.invoke]: utilities.md#func.invoke
369
+ [func.require]: utilities.md#func.require
370
+ [function.objects]: utilities.md#function.objects
371
+ [future.syn]: #future.syn
372
+ [futures]: #futures
373
+ [futures.async]: #futures.async
374
+ [futures.errors]: #futures.errors
375
+ [futures.future.error]: #futures.future.error
376
+ [futures.overview]: #futures.overview
377
+ [futures.promise]: #futures.promise
378
+ [futures.shared.future]: #futures.shared.future
379
+ [futures.state]: #futures.state
380
+ [futures.task]: #futures.task
381
+ [futures.task.general]: #futures.task.general
382
+ [futures.task.members]: #futures.task.members
383
+ [futures.task.nonmembers]: #futures.task.nonmembers
384
+ [futures.unique.future]: #futures.unique.future
385
+ [hazard.pointer.syn]: #hazard.pointer.syn
386
+ [intro.multithread]: basic.md#intro.multithread
387
+ [intro.progress]: basic.md#intro.progress
388
+ [intro.races]: basic.md#intro.races
389
+ [latch.syn]: #latch.syn
390
+ [limits.syn]: support.md#limits.syn
391
+ [mutex.syn]: #mutex.syn
392
+ [rcu.syn]: #rcu.syn
393
+ [res.on.data.races]: library.md#res.on.data.races
394
+ [res.on.exception.handling]: library.md#res.on.exception.handling
395
+ [saferecl]: #saferecl
396
+ [saferecl.general]: #saferecl.general
397
+ [saferecl.hp]: #saferecl.hp
398
+ [saferecl.hp.base]: #saferecl.hp.base
399
+ [saferecl.hp.general]: #saferecl.hp.general
400
+ [saferecl.hp.holder]: #saferecl.hp.holder
401
+ [saferecl.hp.holder.ctor]: #saferecl.hp.holder.ctor
402
+ [saferecl.hp.holder.general]: #saferecl.hp.holder.general
403
+ [saferecl.hp.holder.mem]: #saferecl.hp.holder.mem
404
+ [saferecl.hp.holder.nonmem]: #saferecl.hp.holder.nonmem
405
+ [saferecl.rcu]: #saferecl.rcu
406
+ [saferecl.rcu.base]: #saferecl.rcu.base
407
+ [saferecl.rcu.domain]: #saferecl.rcu.domain
408
+ [saferecl.rcu.domain.func]: #saferecl.rcu.domain.func
409
+ [saferecl.rcu.domain.general]: #saferecl.rcu.domain.general
410
+ [saferecl.rcu.domain.members]: #saferecl.rcu.domain.members
411
+ [saferecl.rcu.general]: #saferecl.rcu.general
412
+ [semaphore.syn]: #semaphore.syn
413
+ [shared.mutex.syn]: #shared.mutex.syn
414
+ [stdatomic.h.syn]: #stdatomic.h.syn
415
+ [stopcallback]: #stopcallback
416
+ [stopcallback.cons]: #stopcallback.cons
417
+ [stopcallback.general]: #stopcallback.general
418
+ [stopcallback.inplace]: #stopcallback.inplace
419
+ [stopcallback.inplace.cons]: #stopcallback.inplace.cons
420
+ [stopcallback.inplace.general]: #stopcallback.inplace.general
421
+ [stopsource]: #stopsource
422
+ [stopsource.cons]: #stopsource.cons
423
+ [stopsource.general]: #stopsource.general
424
+ [stopsource.inplace]: #stopsource.inplace
425
+ [stopsource.inplace.cons]: #stopsource.inplace.cons
426
+ [stopsource.inplace.general]: #stopsource.inplace.general
427
+ [stopsource.inplace.mem]: #stopsource.inplace.mem
428
+ [stopsource.mem]: #stopsource.mem
429
+ [stoptoken]: #stoptoken
430
+ [stoptoken.concepts]: #stoptoken.concepts
431
+ [stoptoken.general]: #stoptoken.general
432
+ [stoptoken.inplace]: #stoptoken.inplace
433
+ [stoptoken.inplace.general]: #stoptoken.inplace.general
434
+ [stoptoken.inplace.mem]: #stoptoken.inplace.mem
435
+ [stoptoken.mem]: #stoptoken.mem
436
+ [stoptoken.never]: #stoptoken.never
437
+ [syserr]: diagnostics.md#syserr
438
+ [syserr.syserr]: diagnostics.md#syserr.syserr
439
+ [term.padding.bits]: basic.md#term.padding.bits
440
+ [term.unevaluated.operand]: expr.md#term.unevaluated.operand
441
+ [thread]: #thread
442
+ [thread.barrier]: #thread.barrier
443
+ [thread.barrier.class]: #thread.barrier.class
444
+ [thread.barrier.general]: #thread.barrier.general
445
+ [thread.condition]: #thread.condition
446
+ [thread.condition.condvar]: #thread.condition.condvar
447
+ [thread.condition.condvarany]: #thread.condition.condvarany
448
+ [thread.condition.condvarany.general]: #thread.condition.condvarany.general
449
+ [thread.condition.general]: #thread.condition.general
450
+ [thread.condition.nonmember]: #thread.condition.nonmember
451
+ [thread.condvarany.intwait]: #thread.condvarany.intwait
452
+ [thread.condvarany.wait]: #thread.condvarany.wait
453
+ [thread.coord]: #thread.coord
454
+ [thread.coord.general]: #thread.coord.general
455
+ [thread.general]: #thread.general
456
+ [thread.jthread.class]: #thread.jthread.class
457
+ [thread.jthread.class.general]: #thread.jthread.class.general
458
+ [thread.jthread.cons]: #thread.jthread.cons
459
+ [thread.jthread.mem]: #thread.jthread.mem
460
+ [thread.jthread.special]: #thread.jthread.special
461
+ [thread.jthread.static]: #thread.jthread.static
462
+ [thread.jthread.stop]: #thread.jthread.stop
463
+ [thread.latch]: #thread.latch
464
+ [thread.latch.class]: #thread.latch.class
465
+ [thread.latch.general]: #thread.latch.general
466
+ [thread.lock]: #thread.lock
467
+ [thread.lock.algorithm]: #thread.lock.algorithm
468
+ [thread.lock.general]: #thread.lock.general
469
+ [thread.lock.guard]: #thread.lock.guard
470
+ [thread.lock.scoped]: #thread.lock.scoped
471
+ [thread.lock.shared]: #thread.lock.shared
472
+ [thread.lock.shared.cons]: #thread.lock.shared.cons
473
+ [thread.lock.shared.general]: #thread.lock.shared.general
474
+ [thread.lock.shared.locking]: #thread.lock.shared.locking
475
+ [thread.lock.shared.mod]: #thread.lock.shared.mod
476
+ [thread.lock.shared.obs]: #thread.lock.shared.obs
477
+ [thread.lock.unique]: #thread.lock.unique
478
+ [thread.lock.unique.cons]: #thread.lock.unique.cons
479
+ [thread.lock.unique.general]: #thread.lock.unique.general
480
+ [thread.lock.unique.locking]: #thread.lock.unique.locking
481
+ [thread.lock.unique.mod]: #thread.lock.unique.mod
482
+ [thread.lock.unique.obs]: #thread.lock.unique.obs
483
+ [thread.mutex]: #thread.mutex
484
+ [thread.mutex.class]: #thread.mutex.class
485
+ [thread.mutex.general]: #thread.mutex.general
486
+ [thread.mutex.recursive]: #thread.mutex.recursive
487
+ [thread.mutex.requirements]: #thread.mutex.requirements
488
+ [thread.mutex.requirements.general]: #thread.mutex.requirements.general
489
+ [thread.mutex.requirements.mutex]: #thread.mutex.requirements.mutex
490
+ [thread.mutex.requirements.mutex.general]: #thread.mutex.requirements.mutex.general
491
+ [thread.once]: #thread.once
492
+ [thread.once.callonce]: #thread.once.callonce
493
+ [thread.once.onceflag]: #thread.once.onceflag
494
+ [thread.req]: #thread.req
495
+ [thread.req.exception]: #thread.req.exception
496
+ [thread.req.lockable]: #thread.req.lockable
497
+ [thread.req.lockable.basic]: #thread.req.lockable.basic
498
+ [thread.req.lockable.general]: #thread.req.lockable.general
499
+ [thread.req.lockable.req]: #thread.req.lockable.req
500
+ [thread.req.lockable.shared]: #thread.req.lockable.shared
501
+ [thread.req.lockable.shared.timed]: #thread.req.lockable.shared.timed
502
+ [thread.req.lockable.timed]: #thread.req.lockable.timed
503
+ [thread.req.native]: #thread.req.native
504
+ [thread.req.paramname]: #thread.req.paramname
505
+ [thread.req.timing]: #thread.req.timing
506
+ [thread.sema]: #thread.sema
507
+ [thread.sema.cnt]: #thread.sema.cnt
508
+ [thread.sema.general]: #thread.sema.general
509
+ [thread.sharedmutex.class]: #thread.sharedmutex.class
510
+ [thread.sharedmutex.requirements]: #thread.sharedmutex.requirements
511
+ [thread.sharedmutex.requirements.general]: #thread.sharedmutex.requirements.general
512
+ [thread.sharedtimedmutex.class]: #thread.sharedtimedmutex.class
513
+ [thread.sharedtimedmutex.requirements]: #thread.sharedtimedmutex.requirements
514
+ [thread.sharedtimedmutex.requirements.general]: #thread.sharedtimedmutex.requirements.general
515
+ [thread.stoptoken]: #thread.stoptoken
516
+ [thread.stoptoken.intro]: #thread.stoptoken.intro
517
+ [thread.stoptoken.syn]: #thread.stoptoken.syn
518
+ [thread.summary]: #thread.summary
519
+ [thread.syn]: #thread.syn
520
+ [thread.thread.algorithm]: #thread.thread.algorithm
521
+ [thread.thread.assign]: #thread.thread.assign
522
+ [thread.thread.class]: #thread.thread.class
523
+ [thread.thread.class.general]: #thread.thread.class.general
524
+ [thread.thread.constr]: #thread.thread.constr
525
+ [thread.thread.destr]: #thread.thread.destr
526
+ [thread.thread.id]: #thread.thread.id
527
+ [thread.thread.member]: #thread.thread.member
528
+ [thread.thread.static]: #thread.thread.static
529
+ [thread.thread.this]: #thread.thread.this
530
+ [thread.threads]: #thread.threads
531
+ [thread.threads.general]: #thread.threads.general
532
+ [thread.timedmutex.class]: #thread.timedmutex.class
533
+ [thread.timedmutex.recursive]: #thread.timedmutex.recursive
534
+ [thread.timedmutex.requirements]: #thread.timedmutex.requirements
535
+ [thread.timedmutex.requirements.general]: #thread.timedmutex.requirements.general
536
+ [time]: time.md#time
537
+ [time.clock]: time.md#time.clock
538
+ [time.clock.req]: time.md#time.clock.req
539
+ [time.duration]: time.md#time.duration
540
+ [time.point]: time.md#time.point
541
+ [unord.hash]: utilities.md#unord.hash
542
+ [util.sharedptr]: mem.md#util.sharedptr
543
+ [util.smartptr.atomic]: #util.smartptr.atomic
544
+ [util.smartptr.atomic.general]: #util.smartptr.atomic.general
545
+ [util.smartptr.atomic.shared]: #util.smartptr.atomic.shared
546
+ [util.smartptr.atomic.weak]: #util.smartptr.atomic.weak
547
+
548
+ [^1]: Implementations for which standard time units are meaningful will
549
+ typically have a steady clock within their hardware implementation.
550
+
551
+ [^2]: That is, atomic operations on the same memory location via two
552
+ different addresses will communicate atomically.