From Jason Turner

[saferecl.hp.holder]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmpncab0htd/{from.md → to.md} +401 -0
tmp/tmpncab0htd/{from.md → to.md} RENAMED
@@ -0,0 +1,401 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #### Class `hazard_pointer` <a id="saferecl.hp.holder">[[saferecl.hp.holder]]</a>
2
+
3
+ ##### General <a id="saferecl.hp.holder.general">[[saferecl.hp.holder.general]]</a>
4
+
5
+ ``` cpp
6
+ namespace std {
7
+ class hazard_pointer {
8
+ public:
9
+ hazard_pointer() noexcept;
10
+ hazard_pointer(hazard_pointer&&) noexcept;
11
+ hazard_pointer& operator=(hazard_pointer&&) noexcept;
12
+ ~hazard_pointer();
13
+
14
+ bool empty() const noexcept;
15
+ template<class T> T* protect(const atomic<T*>& src) noexcept;
16
+ template<class T> bool try_protect(T*& ptr, const atomic<T*>& src) noexcept;
17
+ template<class T> void reset_protection(const T* ptr) noexcept;
18
+ void reset_protection(nullptr_t = nullptr) noexcept;
19
+ void swap(hazard_pointer&) noexcept;
20
+ };
21
+ }
22
+ ```
23
+
24
+ An object of type `hazard_pointer` is either empty or *owns* a hazard
25
+ pointer. Each hazard pointer is owned by exactly one object of type
26
+ `hazard_pointer`.
27
+
28
+ [*Note 1*: An empty `hazard_pointer` object is different from a
29
+ `hazard_pointer` object that owns an unassociated hazard pointer. An
30
+ empty `hazard_pointer` object does not own any hazard
31
+ pointers. — *end note*]
32
+
33
+ ##### Constructors, destructor, and assignment <a id="saferecl.hp.holder.ctor">[[saferecl.hp.holder.ctor]]</a>
34
+
35
+ ``` cpp
36
+ hazard_pointer() noexcept;
37
+ ```
38
+
39
+ *Ensures:* `*this` is empty.
40
+
41
+ ``` cpp
42
+ hazard_pointer(hazard_pointer&& other) noexcept;
43
+ ```
44
+
45
+ *Ensures:* If `other` is empty, `*this` is empty. Otherwise, `*this`
46
+ owns the hazard pointer originally owned by `other`; `other` is empty.
47
+
48
+ ``` cpp
49
+ ~hazard_pointer();
50
+ ```
51
+
52
+ *Effects:* If `*this` is not empty, destroys the hazard pointer owned by
53
+ `*this`, thereby ending its current protection epoch.
54
+
55
+ ``` cpp
56
+ hazard_pointer& operator=(hazard_pointer&& other) noexcept;
57
+ ```
58
+
59
+ *Effects:* If `this == &other` is `true`, no effect. Otherwise, if
60
+ `*this` is not empty, destroys the hazard pointer owned by `*this`,
61
+ thereby ending its current protection epoch.
62
+
63
+ *Ensures:* If `other` was empty, `*this` is empty. Otherwise, `*this`
64
+ owns the hazard pointer originally owned by `other`. If `this != &other`
65
+ is `true`, `other` is empty.
66
+
67
+ *Returns:* `*this`.
68
+
69
+ ##### Member functions <a id="saferecl.hp.holder.mem">[[saferecl.hp.holder.mem]]</a>
70
+
71
+ ``` cpp
72
+ bool empty() const noexcept;
73
+ ```
74
+
75
+ *Returns:* `true` if and only if `*this` is empty.
76
+
77
+ ``` cpp
78
+ template<class T> T* protect(const atomic<T*>& src) noexcept;
79
+ ```
80
+
81
+ *Effects:* Equivalent to:
82
+
83
+ ``` cpp
84
+ T* ptr = src.load(memory_order::relaxed);
85
+ while (!try_protect(ptr, src)) {}
86
+ return ptr;
87
+ ```
88
+
89
+ ``` cpp
90
+ template<class T> bool try_protect(T*& ptr, const atomic<T*>& src) noexcept;
91
+ ```
92
+
93
+ *Mandates:* `T` is a hazard-protectable type.
94
+
95
+ *Preconditions:* `*this` is not empty.
96
+
97
+ *Effects:* Performs the following steps in order:
98
+
99
+ - Initializes a variable `old` of type `T*` with the value of `ptr`.
100
+ - Evaluates `reset_protection(old)`.
101
+ - Assigns the value of `src.load(memory_order::acquire)` to `ptr`.
102
+ - If `old == ptr` is `false`, evaluates `reset_protection()`.
103
+
104
+ *Returns:* `old == ptr`.
105
+
106
+ ``` cpp
107
+ template<class T> void reset_protection(const T* ptr) noexcept;
108
+ ```
109
+
110
+ *Mandates:* `T` is a hazard-protectable type.
111
+
112
+ *Preconditions:* `*this` is not empty.
113
+
114
+ *Effects:* If `ptr` is a null pointer value, invokes
115
+ `reset_protection()`. Otherwise, associates the hazard pointer owned by
116
+ `*this` with `*ptr`, thereby ending the current protection epoch.
117
+
118
+ *Complexity:* Constant.
119
+
120
+ ``` cpp
121
+ void reset_protection(nullptr_t = nullptr) noexcept;
122
+ ```
123
+
124
+ *Preconditions:* `*this` is not empty.
125
+
126
+ *Ensures:* The hazard pointer owned by `*this` is unassociated.
127
+
128
+ *Complexity:* Constant.
129
+
130
+ ``` cpp
131
+ void swap(hazard_pointer& other) noexcept;
132
+ ```
133
+
134
+ *Effects:* Swaps the hazard pointer ownership of this object with that
135
+ of `other`.
136
+
137
+ [*Note 1*: The owned hazard pointers, if any, remain unchanged during
138
+ the swap and continue to be associated with the respective objects that
139
+ they were protecting before the swap, if any. No protection epochs are
140
+ ended or initiated. — *end note*]
141
+
142
+ *Complexity:* Constant.
143
+
144
+ ##### Non-member functions <a id="saferecl.hp.holder.nonmem">[[saferecl.hp.holder.nonmem]]</a>
145
+
146
+ ``` cpp
147
+ hazard_pointer make_hazard_pointer();
148
+ ```
149
+
150
+ *Effects:* Constructs a hazard pointer.
151
+
152
+ *Returns:* A `hazard_pointer` object that owns the newly-constructed
153
+ hazard pointer.
154
+
155
+ *Throws:* May throw `bad_alloc` if memory for the hazard pointer could
156
+ not be allocated.
157
+
158
+ ``` cpp
159
+ void swap(hazard_pointer& a, hazard_pointer& b) noexcept;
160
+ ```
161
+
162
+ *Effects:* Equivalent to `a.swap(b)`.
163
+
164
+ <!-- Link reference definitions -->
165
+ [alg.min.max]: algorithms.md#alg.min.max
166
+ [alg.sorting]: algorithms.md#alg.sorting
167
+ [allocator.requirements.general]: library.md#allocator.requirements.general
168
+ [atomic.types.int.comp]: #atomic.types.int.comp
169
+ [atomic.types.pointer.comp]: #atomic.types.pointer.comp
170
+ [atomics]: #atomics
171
+ [atomics.alias]: #atomics.alias
172
+ [atomics.fences]: #atomics.fences
173
+ [atomics.flag]: #atomics.flag
174
+ [atomics.general]: #atomics.general
175
+ [atomics.lockfree]: #atomics.lockfree
176
+ [atomics.nonmembers]: #atomics.nonmembers
177
+ [atomics.order]: #atomics.order
178
+ [atomics.ref.float]: #atomics.ref.float
179
+ [atomics.ref.generic]: #atomics.ref.generic
180
+ [atomics.ref.generic.general]: #atomics.ref.generic.general
181
+ [atomics.ref.int]: #atomics.ref.int
182
+ [atomics.ref.memop]: #atomics.ref.memop
183
+ [atomics.ref.ops]: #atomics.ref.ops
184
+ [atomics.ref.pointer]: #atomics.ref.pointer
185
+ [atomics.syn]: #atomics.syn
186
+ [atomics.types.float]: #atomics.types.float
187
+ [atomics.types.generic]: #atomics.types.generic
188
+ [atomics.types.generic.general]: #atomics.types.generic.general
189
+ [atomics.types.int]: #atomics.types.int
190
+ [atomics.types.memop]: #atomics.types.memop
191
+ [atomics.types.operations]: #atomics.types.operations
192
+ [atomics.types.pointer]: #atomics.types.pointer
193
+ [atomics.wait]: #atomics.wait
194
+ [barrier.syn]: #barrier.syn
195
+ [basic.align]: basic.md#basic.align
196
+ [basic.fundamental]: basic.md#basic.fundamental
197
+ [basic.life]: basic.md#basic.life
198
+ [basic.stc.general]: basic.md#basic.stc.general
199
+ [basic.stc.thread]: basic.md#basic.stc.thread
200
+ [bitmask.types]: library.md#bitmask.types
201
+ [cfenv]: numerics.md#cfenv
202
+ [class.prop]: class.md#class.prop
203
+ [compliance]: library.md#compliance
204
+ [concept.booleantestable]: concepts.md#concept.booleantestable
205
+ [condition.variable.syn]: #condition.variable.syn
206
+ [conv.rval]: expr.md#conv.rval
207
+ [cpp17.defaultconstructible]: #cpp17.defaultconstructible
208
+ [cpp17.destructible]: #cpp17.destructible
209
+ [cpp17.lessthancomparable]: #cpp17.lessthancomparable
210
+ [cpp17.moveassignable]: #cpp17.moveassignable
211
+ [cpp17.moveconstructible]: #cpp17.moveconstructible
212
+ [defns.block]: intro.md#defns.block
213
+ [except.terminate]: except.md#except.terminate
214
+ [expr.pre]: expr.md#expr.pre
215
+ [expr.rel]: expr.md#expr.rel
216
+ [format.string.std]: text.md#format.string.std
217
+ [func.invoke]: utilities.md#func.invoke
218
+ [func.require]: utilities.md#func.require
219
+ [function.objects]: utilities.md#function.objects
220
+ [future.syn]: #future.syn
221
+ [futures]: #futures
222
+ [futures.async]: #futures.async
223
+ [futures.errors]: #futures.errors
224
+ [futures.future.error]: #futures.future.error
225
+ [futures.overview]: #futures.overview
226
+ [futures.promise]: #futures.promise
227
+ [futures.shared.future]: #futures.shared.future
228
+ [futures.state]: #futures.state
229
+ [futures.task]: #futures.task
230
+ [futures.task.general]: #futures.task.general
231
+ [futures.task.members]: #futures.task.members
232
+ [futures.task.nonmembers]: #futures.task.nonmembers
233
+ [futures.unique.future]: #futures.unique.future
234
+ [hazard.pointer.syn]: #hazard.pointer.syn
235
+ [intro.multithread]: basic.md#intro.multithread
236
+ [intro.progress]: basic.md#intro.progress
237
+ [intro.races]: basic.md#intro.races
238
+ [latch.syn]: #latch.syn
239
+ [limits.syn]: support.md#limits.syn
240
+ [mutex.syn]: #mutex.syn
241
+ [rcu.syn]: #rcu.syn
242
+ [res.on.data.races]: library.md#res.on.data.races
243
+ [res.on.exception.handling]: library.md#res.on.exception.handling
244
+ [saferecl]: #saferecl
245
+ [saferecl.general]: #saferecl.general
246
+ [saferecl.hp]: #saferecl.hp
247
+ [saferecl.hp.base]: #saferecl.hp.base
248
+ [saferecl.hp.general]: #saferecl.hp.general
249
+ [saferecl.hp.holder]: #saferecl.hp.holder
250
+ [saferecl.hp.holder.ctor]: #saferecl.hp.holder.ctor
251
+ [saferecl.hp.holder.general]: #saferecl.hp.holder.general
252
+ [saferecl.hp.holder.mem]: #saferecl.hp.holder.mem
253
+ [saferecl.hp.holder.nonmem]: #saferecl.hp.holder.nonmem
254
+ [saferecl.rcu]: #saferecl.rcu
255
+ [saferecl.rcu.base]: #saferecl.rcu.base
256
+ [saferecl.rcu.domain]: #saferecl.rcu.domain
257
+ [saferecl.rcu.domain.func]: #saferecl.rcu.domain.func
258
+ [saferecl.rcu.domain.general]: #saferecl.rcu.domain.general
259
+ [saferecl.rcu.domain.members]: #saferecl.rcu.domain.members
260
+ [saferecl.rcu.general]: #saferecl.rcu.general
261
+ [semaphore.syn]: #semaphore.syn
262
+ [shared.mutex.syn]: #shared.mutex.syn
263
+ [stdatomic.h.syn]: #stdatomic.h.syn
264
+ [stopcallback]: #stopcallback
265
+ [stopcallback.cons]: #stopcallback.cons
266
+ [stopcallback.general]: #stopcallback.general
267
+ [stopcallback.inplace]: #stopcallback.inplace
268
+ [stopcallback.inplace.cons]: #stopcallback.inplace.cons
269
+ [stopcallback.inplace.general]: #stopcallback.inplace.general
270
+ [stopsource]: #stopsource
271
+ [stopsource.cons]: #stopsource.cons
272
+ [stopsource.general]: #stopsource.general
273
+ [stopsource.inplace]: #stopsource.inplace
274
+ [stopsource.inplace.cons]: #stopsource.inplace.cons
275
+ [stopsource.inplace.general]: #stopsource.inplace.general
276
+ [stopsource.inplace.mem]: #stopsource.inplace.mem
277
+ [stopsource.mem]: #stopsource.mem
278
+ [stoptoken]: #stoptoken
279
+ [stoptoken.concepts]: #stoptoken.concepts
280
+ [stoptoken.general]: #stoptoken.general
281
+ [stoptoken.inplace]: #stoptoken.inplace
282
+ [stoptoken.inplace.general]: #stoptoken.inplace.general
283
+ [stoptoken.inplace.mem]: #stoptoken.inplace.mem
284
+ [stoptoken.mem]: #stoptoken.mem
285
+ [stoptoken.never]: #stoptoken.never
286
+ [syserr]: diagnostics.md#syserr
287
+ [syserr.syserr]: diagnostics.md#syserr.syserr
288
+ [term.padding.bits]: basic.md#term.padding.bits
289
+ [term.unevaluated.operand]: expr.md#term.unevaluated.operand
290
+ [thread]: #thread
291
+ [thread.barrier]: #thread.barrier
292
+ [thread.barrier.class]: #thread.barrier.class
293
+ [thread.barrier.general]: #thread.barrier.general
294
+ [thread.condition]: #thread.condition
295
+ [thread.condition.condvar]: #thread.condition.condvar
296
+ [thread.condition.condvarany]: #thread.condition.condvarany
297
+ [thread.condition.condvarany.general]: #thread.condition.condvarany.general
298
+ [thread.condition.general]: #thread.condition.general
299
+ [thread.condition.nonmember]: #thread.condition.nonmember
300
+ [thread.condvarany.intwait]: #thread.condvarany.intwait
301
+ [thread.condvarany.wait]: #thread.condvarany.wait
302
+ [thread.coord]: #thread.coord
303
+ [thread.coord.general]: #thread.coord.general
304
+ [thread.general]: #thread.general
305
+ [thread.jthread.class]: #thread.jthread.class
306
+ [thread.jthread.class.general]: #thread.jthread.class.general
307
+ [thread.jthread.cons]: #thread.jthread.cons
308
+ [thread.jthread.mem]: #thread.jthread.mem
309
+ [thread.jthread.special]: #thread.jthread.special
310
+ [thread.jthread.static]: #thread.jthread.static
311
+ [thread.jthread.stop]: #thread.jthread.stop
312
+ [thread.latch]: #thread.latch
313
+ [thread.latch.class]: #thread.latch.class
314
+ [thread.latch.general]: #thread.latch.general
315
+ [thread.lock]: #thread.lock
316
+ [thread.lock.algorithm]: #thread.lock.algorithm
317
+ [thread.lock.general]: #thread.lock.general
318
+ [thread.lock.guard]: #thread.lock.guard
319
+ [thread.lock.scoped]: #thread.lock.scoped
320
+ [thread.lock.shared]: #thread.lock.shared
321
+ [thread.lock.shared.cons]: #thread.lock.shared.cons
322
+ [thread.lock.shared.general]: #thread.lock.shared.general
323
+ [thread.lock.shared.locking]: #thread.lock.shared.locking
324
+ [thread.lock.shared.mod]: #thread.lock.shared.mod
325
+ [thread.lock.shared.obs]: #thread.lock.shared.obs
326
+ [thread.lock.unique]: #thread.lock.unique
327
+ [thread.lock.unique.cons]: #thread.lock.unique.cons
328
+ [thread.lock.unique.general]: #thread.lock.unique.general
329
+ [thread.lock.unique.locking]: #thread.lock.unique.locking
330
+ [thread.lock.unique.mod]: #thread.lock.unique.mod
331
+ [thread.lock.unique.obs]: #thread.lock.unique.obs
332
+ [thread.mutex]: #thread.mutex
333
+ [thread.mutex.class]: #thread.mutex.class
334
+ [thread.mutex.general]: #thread.mutex.general
335
+ [thread.mutex.recursive]: #thread.mutex.recursive
336
+ [thread.mutex.requirements]: #thread.mutex.requirements
337
+ [thread.mutex.requirements.general]: #thread.mutex.requirements.general
338
+ [thread.mutex.requirements.mutex]: #thread.mutex.requirements.mutex
339
+ [thread.mutex.requirements.mutex.general]: #thread.mutex.requirements.mutex.general
340
+ [thread.once]: #thread.once
341
+ [thread.once.callonce]: #thread.once.callonce
342
+ [thread.once.onceflag]: #thread.once.onceflag
343
+ [thread.req]: #thread.req
344
+ [thread.req.exception]: #thread.req.exception
345
+ [thread.req.lockable]: #thread.req.lockable
346
+ [thread.req.lockable.basic]: #thread.req.lockable.basic
347
+ [thread.req.lockable.general]: #thread.req.lockable.general
348
+ [thread.req.lockable.req]: #thread.req.lockable.req
349
+ [thread.req.lockable.shared]: #thread.req.lockable.shared
350
+ [thread.req.lockable.shared.timed]: #thread.req.lockable.shared.timed
351
+ [thread.req.lockable.timed]: #thread.req.lockable.timed
352
+ [thread.req.native]: #thread.req.native
353
+ [thread.req.paramname]: #thread.req.paramname
354
+ [thread.req.timing]: #thread.req.timing
355
+ [thread.sema]: #thread.sema
356
+ [thread.sema.cnt]: #thread.sema.cnt
357
+ [thread.sema.general]: #thread.sema.general
358
+ [thread.sharedmutex.class]: #thread.sharedmutex.class
359
+ [thread.sharedmutex.requirements]: #thread.sharedmutex.requirements
360
+ [thread.sharedmutex.requirements.general]: #thread.sharedmutex.requirements.general
361
+ [thread.sharedtimedmutex.class]: #thread.sharedtimedmutex.class
362
+ [thread.sharedtimedmutex.requirements]: #thread.sharedtimedmutex.requirements
363
+ [thread.sharedtimedmutex.requirements.general]: #thread.sharedtimedmutex.requirements.general
364
+ [thread.stoptoken]: #thread.stoptoken
365
+ [thread.stoptoken.intro]: #thread.stoptoken.intro
366
+ [thread.stoptoken.syn]: #thread.stoptoken.syn
367
+ [thread.summary]: #thread.summary
368
+ [thread.syn]: #thread.syn
369
+ [thread.thread.algorithm]: #thread.thread.algorithm
370
+ [thread.thread.assign]: #thread.thread.assign
371
+ [thread.thread.class]: #thread.thread.class
372
+ [thread.thread.class.general]: #thread.thread.class.general
373
+ [thread.thread.constr]: #thread.thread.constr
374
+ [thread.thread.destr]: #thread.thread.destr
375
+ [thread.thread.id]: #thread.thread.id
376
+ [thread.thread.member]: #thread.thread.member
377
+ [thread.thread.static]: #thread.thread.static
378
+ [thread.thread.this]: #thread.thread.this
379
+ [thread.threads]: #thread.threads
380
+ [thread.threads.general]: #thread.threads.general
381
+ [thread.timedmutex.class]: #thread.timedmutex.class
382
+ [thread.timedmutex.recursive]: #thread.timedmutex.recursive
383
+ [thread.timedmutex.requirements]: #thread.timedmutex.requirements
384
+ [thread.timedmutex.requirements.general]: #thread.timedmutex.requirements.general
385
+ [time]: time.md#time
386
+ [time.clock]: time.md#time.clock
387
+ [time.clock.req]: time.md#time.clock.req
388
+ [time.duration]: time.md#time.duration
389
+ [time.point]: time.md#time.point
390
+ [unord.hash]: utilities.md#unord.hash
391
+ [util.sharedptr]: mem.md#util.sharedptr
392
+ [util.smartptr.atomic]: #util.smartptr.atomic
393
+ [util.smartptr.atomic.general]: #util.smartptr.atomic.general
394
+ [util.smartptr.atomic.shared]: #util.smartptr.atomic.shared
395
+ [util.smartptr.atomic.weak]: #util.smartptr.atomic.weak
396
+
397
+ [^1]: Implementations for which standard time units are meaningful will
398
+ typically have a steady clock within their hardware implementation.
399
+
400
+ [^2]: That is, atomic operations on the same memory location via two
401
+ different addresses will communicate atomically.