Init
This commit is contained in:
127
cppdraft/saferecl/hp/general.md
Normal file
127
cppdraft/saferecl/hp/general.md
Normal file
@@ -0,0 +1,127 @@
|
||||
[saferecl.hp.general]
|
||||
|
||||
# 32 Concurrency support library [[thread]](./#thread)
|
||||
|
||||
## 32.11 Safe reclamation [[saferecl]](saferecl#hp.general)
|
||||
|
||||
### 32.11.3 Hazard pointers [[saferecl.hp]](saferecl.hp#general)
|
||||
|
||||
#### 32.11.3.1 General [saferecl.hp.general]
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L13272)
|
||||
|
||||
A hazard pointer is a single-writer multi-reader pointer
|
||||
that can be owned by at most one thread at any time[.](#1.sentence-1)
|
||||
|
||||
Only the owner of the hazard pointer can set its value,
|
||||
while any number of threads may read its value[.](#1.sentence-2)
|
||||
|
||||
The owner thread sets the value of a hazard pointer to point to an object
|
||||
in order to indicate to concurrent threadsâwhich
|
||||
may delete such an objectâthat
|
||||
the object is not yet safe to delete[.](#1.sentence-3)
|
||||
|
||||
[2](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L13283)
|
||||
|
||||
A class type T is [*hazard-protectable*](#def:hazard-protectable "32.11.3.1 General [saferecl.hp.general]") if it has exactly one base class of type hazard_pointer_obj_base<T, D> for some D,
|
||||
that base is public and non-virtual, and
|
||||
it has no base classes of type hazard_pointer_obj_base<T2, D2> for any other combination T2, D2[.](#2.sentence-1)
|
||||
|
||||
An object is [*hazard-protectable*](#def:hazard-protectable "32.11.3.1 General [saferecl.hp.general]") if it is of hazard-protectable type[.](#2.sentence-2)
|
||||
|
||||
[3](#3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L13292)
|
||||
|
||||
The time span between creation and destruction of a hazard pointer h is partitioned into a series of [*protection epochs*](#def:epoch,protection "32.11.3.1 General [saferecl.hp.general]");
|
||||
in each protection epoch,h either is [*associated with*](#def:hazard_pointer,associated "32.11.3.1 General [saferecl.hp.general]") a hazard-protectable object, or is [*unassociated*](#def:hazard_pointer,unassociated "32.11.3.1 General [saferecl.hp.general]")[.](#3.sentence-1)
|
||||
|
||||
Upon creation, a hazard pointer is unassociated[.](#3.sentence-2)
|
||||
|
||||
Changing the association (possibly to the same object)
|
||||
initiates a new protection epoch and ends the preceding one[.](#3.sentence-3)
|
||||
|
||||
[4](#4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L13302)
|
||||
|
||||
An object x of hazard-protectable type T is[*retired*](#def:retired "32.11.3.1 General [saferecl.hp.general]") with a deleter of type D when the member function hazard_pointer_obj_base<T, D>::retire is invoked on x[.](#4.sentence-1)
|
||||
|
||||
Any given object x shall be retired at most once[.](#4.sentence-2)
|
||||
|
||||
[5](#5)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L13309)
|
||||
|
||||
A retired object x is [*reclaimed*](#def:reclaimed "32.11.3.1 General [saferecl.hp.general]") by invoking its deleter with a pointer to x;
|
||||
the behavior is undefined if that invocation exits via an exception[.](#5.sentence-1)
|
||||
|
||||
[6](#6)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L13314)
|
||||
|
||||
A hazard-protectable object x is [*possibly-reclaimable*](#def:possibly-reclaimable "32.11.3.1 General [saferecl.hp.general]") with respect to an evaluation A if
|
||||
|
||||
- [(6.1)](#6.1)
|
||||
|
||||
x is not reclaimed; and
|
||||
|
||||
- [(6.2)](#6.2)
|
||||
|
||||
x is retired in an evaluation R andA does not happen before R; and
|
||||
|
||||
- [(6.3)](#6.3)
|
||||
|
||||
for all hazard pointers h and for every protection epoch E of h during which h is associated with x:
|
||||
* [(6.3.1)](#6.3.1)
|
||||
|
||||
if the beginning of E happens before R,
|
||||
the end of E strongly happens before A; and
|
||||
|
||||
* [(6.3.2)](#6.3.2)
|
||||
|
||||
if E began by an evaluation of try_protect with argument src,
|
||||
label its atomic load operation L[.](#6.sentence-1)
|
||||
If there exists an atomic modification B on src such that L observes a modification that is modification-ordered before B, andB happens before x is retired,
|
||||
the end of E strongly happens before A[.](#6.3.2.sentence-2)
|
||||
[*Note [1](#note-1)*:
|
||||
In typical use, a store to src sequenced before retiring x will be such an atomic operation B[.](#6.3.2.sentence-3)
|
||||
â *end note*]
|
||||
|
||||
[*Note [2](#note-2)*:
|
||||
The latter two conditions convey the informal notion
|
||||
that a protection epoch that began before retiring x,
|
||||
as implied either by the happens-before relation or
|
||||
the coherence order of some source,
|
||||
delays the reclamation of x[.](#6.3.sentence-2)
|
||||
â *end note*]
|
||||
|
||||
[7](#7)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L13351)
|
||||
|
||||
The number of possibly-reclaimable objects has an unspecified bound[.](#7.sentence-1)
|
||||
|
||||
[*Note [3](#note-3)*:
|
||||
|
||||
The bound can be a function of the number of hazard pointers,
|
||||
the number of threads that retire objects, and
|
||||
the number of threads that use hazard pointers[.](#7.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[*Example [1](#example-1)*:
|
||||
|
||||
The following example shows how hazard pointers allow updates to be carried out
|
||||
in the presence of concurrent readers[.](#7.sentence-3)
|
||||
|
||||
The object of type hazard_pointer in print_name protects the object *ptr from being reclaimed by ptr->retire until the end of the protection epoch[.](#7.sentence-4)
|
||||
|
||||
struct Name : public hazard_pointer_obj_base<Name> { /* details */ };
|
||||
atomic<Name*> name;// called often and in parallel!void print_name() { hazard_pointer h = make_hazard_pointer();
|
||||
Name* ptr = h.protect(name); // Protection epoch starts// ... safe to access *ptr} // Protection epoch ends.// called rarely, but possibly concurrently with print_namevoid update_name(Name* new_name) { Name* ptr = name.exchange(new_name);
|
||||
ptr->retire();} â *end example*]
|
||||
Reference in New Issue
Block a user