blob: 25512ba9453bddd3cbee073884f6110d7ef8dd82 [file] [log] [blame]
% together/hazptr.tex
% mainfile: ../perfbook.tex
% SPDX-License-Identifier: CC-BY-SA-3.0
\section{Hazard-Pointer Helpers}
\label{sec:together:Hazard-Pointer Helpers}
%
\epigraph{It's the little things that count, hundreds of them.}
{Cliff Shaw}
This section looks at some issues that can be addressed with the
help of hazard pointers.
In addition, hazard pointers can sometimes be used to address the
issues called out in \cref{sec:together:RCU Rescues}, and vice versa.
\subsection{Scalable Reference Count}
\label{sec:together:Scalable Reference Count}
Suppose a reference count is becoming a performance or scalability
bottleneck.
What can you do?
One approach is to instead use \IXpl{hazard pointer}.
There are some differences, perhaps most notably that with
hazard pointers it is extremely expensive to determine when
the corresponding reference count has reached zero.
One way to work around this problem is to split the load between
reference counters and hazard pointers.
Each data element has a reference counter that tracks the number
of other data elements referencing this element on the one hand,
and readers use hazard pointers on the other.
Making this arrangement work both efficiently and correctly can be
quite challenging, and so interested readers are invited to examine
the UnboundedQueue and ConcurrentHashMap data structures implemented in
Folly open-source library.\footnote{
\url{https://github.com/facebook/folly}}
\subsection{Long-Duration Accesses}
\label{sec:together:Long-Duration Accesses}
Suppose a reader-writer-locking reader is holding the lock for so
long that updates are excessively delayed.
If that reader can reasonably be converted to use reference counting
instead of reader-writer locking, but if performance and scalability
considerations prevent use of actual reference counters, then hazard
pointers provides a scalable variant of reference counting.
The key point is that where reader-writer locking readers block all
updates for that lock, hazard pointers instead simply hang onto the
data that is actually needed, while still allowing updates to proceed.
If the reader cannot be reasonably be converted to use reference
counting, the tricks in \cref{sec:together:Long-Duration Accesses Two}
might be helpful.
% @@@ papers to maybe cite: OrcGC, ThreadScan, Fast and Robust Memory...
% @@@ Generalized hazard-pointer link counts, if and when.
% @@@ Representative hazard pointer for list, so that nothing
% @@@ in list gets freed until list's hazard pointer is released.
% @@@ Midpoint between hazard pointers and RCU, in fact, you
% @@@ could argue that Tasks Trace RCU with read-side memory
% @@@ barriers is sort of a per-CPU hazard pointers implementing RCU.
% @@@ Except no re-checking because CPUs cannot be freed.