Hazard Pointers in C++26
Hazard pointers provide garbage collection in C++ and solve the ABA problem.

First of all. What is a hazard pointer? Proposal P2530R3 gives a nice explanation:
A hazard pointer is a single-writer multi-reader pointer that can be owned by at most one thread at any time. Only the owner of the hazard pointer can set its value, while any number of threads may read its value. A thread that is about to access dynamic objects acquires ownership of hazard pointer(s) to protect such objects from being reclaimed. The owner thread sets the value of a hazard pointer to point to an object in order to indicate to concurrent threads — that may remove such object — that the object is not yet safe to reclaim.
Hazard pointers are owned and written by threads that act as accessors/protectors (i.e., protect removable objects from unsafe reclamation in order to access such objects) and are read by threads that act as removers/reclaimers (i.e., may remove and try to reclaim objects). Removers retire removed objects to the hazard pointer library (i.e., pass the responsibility for reclaiming the objects to the library code rather than normally by user code). The set of protector and remover threads may overlap.
To make it short, Hazard Pointers guarantee that the referenced objects are deleted if they are no longer needed.
Hazard pointers perform and interact with protection and deferred reclamation.
Protection
They guarantee that objects are only destroyed if they are no longer needed.
Deferred Reclamation
Collect the retired objects and extract their values into a set. Read the values of all hazard pointers and compare them with the addresses of the extracted values in the set. If a value from the set is not found in all values of the hazard pointers, it can be destroyed. If found, it will go back in the set of retired objects.
So, what are the advantages of hazard pointers? My answer consists of two points: correctness and performance.
Advantage
I would like to start with correctness.
Correctness
The advantage of hazard pointers can be illustrated with a simple example.
Modernes C++ Mentoring
Do you want to stay informed: Subscribe.
Node* currentNode = this->head; Node* nextNode = currentNode->next;
The critical question regarding this small code snippet is: how can we guarantee that currentNode
is still valid? While one thread is executing this code, another thread may already be executing currentNode
.
Atomic compare-and-swap (CAS) operations exacerbate this problem. In C++, the compare_exchange_strong
operation is typically used for this purpose. However, CAS operations suffer from the ABA problem. I discuss the ABA problem in more detail in my article Deferred Reclamation in C++26: Read-Copy Update and Hazard Pointers. The solution to the problem is relatively obvious: automatic garbage collection. This is exactly what hazard pointers offer.
Performance
With C++14, reader-writer locks were introduced. With these special locks, reading threads are treated differently than writing threads. This means that any number of reading threads can be executed simultaneously, but only one writing thread. As a result, reader-writer locks promise a performance improvement over exclusive locks. More details on reader-writer locks can be found in my earlier article Reader-Writer Locks.
Proposal P2530R3 provides a nice example of a data structure that is predominantly read. A classic reader-writer lock and hazard pointer are used.

Typical latency of hazard_pointer construction/destruction in the Folly implementation on contemporary commodity server is approximately 4 ns. Using a pre-constructed hazard_pointer typically takes under one nanosecond to stop for protection.
Facebook’s open library Folly provides the reference implementation of hazard pointers.
Interface
Hazard Pointers consisting of the two classes hazard_pointer_obj_base
and hazard_pointer
and the two functions make_hazard_pointer
and swap
.
hazard_pointer_obj_base
is the base class of the protected class, and provides the functionretire
.hazard_pointer
provides the functionsempty, protect, try_protect, reset_protection,
andswap.
make_hazard_pointer
creates a hazard pointer.
What’s next?
RCU stands for Read Copy Update, a synchronization technique for almost read-only data structures created by Paul McKenney and used in the Linux kernel since 2002. RCU is currently mentioned in connection with hazard pointers.
Thanks a lot to my Patreon Supporters: Matt Braun, Roman Postanciuc, Tobias Zindl, G Prvulovic, Reinhold Dröge, Abernitzke, Frank Grimm, Sakib, Broeserl, António Pina, Sergey Agafyin, Андрей Бурмистров, Jake, GS, Lawton Shoemake, Jozo Leko, John Breland, Venkat Nandam, Jose Francisco, Douglas Tinkham, Kuchlong Kuchlong, Robert Blanch, Truels Wissneth, Mario Luoni, Friedrich Huber, lennonli, Pramod Tikare Muralidhara, Peter Ware, Daniel Hufschläger, Alessandro Pezzato, Bob Perry, Satish Vangipuram, Andi Ireland, Richard Ohnemus, Michael Dunsky, Leo Goodstadt, John Wiederhirn, Yacob Cohen-Arazi, Florian Tischler, Robin Furness, Michael Young, Holger Detering, Bernd Mühlhaus, Stephen Kelley, Kyle Dean, Tusar Palauri, Juan Dent, George Liao, Daniel Ceperley, Jon T Hess, Stephen Totten, Wolfgang Fütterer, Matthias Grün, Phillip Diekmann, Ben Atakora, Ann Shatoff, Rob North, Bhavith C Achar, Marco Parri Empoli, Philipp Lenk, Charles-Jianye Chen, Keith Jeffery, Matt Godbolt, Honey Sukesan, bruce_lee_wayne, Silviu Ardelean, schnapper79, and Seeker.
Thanks, in particular, to Jon Hess, Lakshman, Christian Wittenhorst, Sherhy Pyton, Dendi Suhubdy, Sudhakar Belagurusamy, Richard Sargeant, Rusty Fleming, John Nebel, Mipko, Alicja Kaminska, Slavko Radman, and David Poole.
My special thanks to Embarcadero | ![]() |
My special thanks to PVS-Studio | ![]() |
My special thanks to Tipi.build | ![]() |
My special thanks to Take Up Code | ![]() |
My special thanks to SHAVEDYAKS | ![]() |
Modernes C++ GmbH
Modernes C++ Mentoring (English)
Rainer Grimm
Yalovastraße 20
72108 Rottenburg
Mail: schulung@ModernesCpp.de
Mentoring: www.ModernesCpp.org