[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 for some D, that base is public and non-virtual, and it has no base classes of type hazard_pointer_obj_base 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​::​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 { /* details */ }; atomic 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*]