[PATCH v2 0/3] libstdc++: Implement std::hazard_pointer (P2530R3)
Paul Xi Cao <[email protected]>
| Newsgroups | gmane.comp.gcc.patches,gmane.comp.gcc.libstdc++.devel |
|---|---|
| Message-ID | <[email protected]> |
This is v2 of the std::hazard_pointer series, addressing Thomas
Rodgers' review of v1:
https://gcc.gnu.org/pipermail/libstdc++/2026-July/067282.html
The public API is unchanged from v1; everything below is internal.
Point-by-point answers, the measurements, and two questions for the
maintainers are in my reply on that thread.
R1 reclaim-side ordering fixed seq_cst fence in _M_synchronize,
between collect and scan
R2 retire() allocates fixed intrusive retire link in the
object -- this freezes the
layout of a type users derive
from, see below
R3 slot acquire/release fixed lock-free claim and release;
3.8x at 16 threads, 1.13x at
one, and one case slower
than v1
R4 concurrent.cc could not fixed rewritten and validated by
fail negative control
R5 version.h not regenerated fixed self-found; the feature-test
macro was not gthread/hosted
gated in v1
R6 ChangeLog indentation fixed self-found
Series layout, unchanged from v1:
[1/3] libstdc++: Add infrastructure for std::hazard_pointer (C++26)
<hazard_pointer> header, bits/hazard_ptr.h stub, version.def
entry, Makefile.am registration, feature-test macro tests.
Now includes the regenerated version.h (R5).
[2/3] libstdc++: Implement std::hazard_pointer (P2530R3)
Full implementation. Carries R1, R2 and R3; the commit
message has the reasoning for each.
[3/3] libstdc++: Add tests for std::hazard_pointer
20 files, up from 18: the rewritten concurrent.cc (R4), plus
the new retire_no_alloc.cc and layout.cc, which pin the two
claims R2 makes. With the two feature-test macro tests in
1/3 that is 22 in 30_threads/hazard_pointer/.
One item needs a maintainer decision rather than a review comment.
Fixing retire() requires the retire-list link to live inside
hazard_pointer_obj_base, which changes the layout of a
standard-specified type that users derive from -- so its size lands in
user binaries, and doc/xml/manual/abi.xml lists that as a prohibited
change after release. v2 therefore takes P2530R3 sec. 1.5 at its word
and reserves the two extensions it names, a cohort pointer and a
64-bit counter, now rather than later. Whether this is the right
moment to freeze that layout is a maintainer call; the argument is in
the review thread.
Tested on x86_64-pc-linux-gnu: 42/42 pass at -std=gnu++26 across the
22 files, including the negative compile tests, and both negative
controls fire. In the standalone prototype the same algorithm is ASan
and TSan clean, gated by three herd7 litmus tests in CI, and green on
gcc, clang and MSVC. I can post the litmus tests separately if that
is useful; they have no home in this tree.
The concurrent tests still run without a TSan target_board, as in v1.
The prototype runs the same test bodies under -fsanitize=thread in CI;
happy to add a parallel run under the libstdc++ tsan options if
reviewers would rather have it in the series than take my word for it.
Prototype repository, as in v1 -- single-header, namespace proto, and
the source of the measurements in the review thread:
https://github.com/PaulXiCao/hazard_pointer_prototype
Still deferred, as in v1: contracts-based preconditions, waiting on a
macro that distinguishes "contracts are evaluated" from
__cpp_contracts. Deferred deliberately, and new in v2: per-thread
record caching, which is the fix for the one case that is slower than
v1. It is ABI-neutral, so it need not land with this series; the
argument for deferring rather than holding v2 is in the review thread.
The header is reformatted to libstdc++ house style in this version,
which makes a range-diff against v1 useless, hence the summary above.
Disclosure: the prose of this message was rephrased with LLM
assistance.
Paul Xi Cao (3):
libstdc++: Add infrastructure for std::hazard_pointer (C++26)
libstdc++: Implement std::hazard_pointer (P2530R3)
libstdc++: Add tests for std::hazard_pointer
libstdc++-v3/include/Makefile.am | 2 +
libstdc++-v3/include/Makefile.in | 2 +
libstdc++-v3/include/bits/hazard_ptr.h | 1089 +++++++++++++++++
libstdc++-v3/include/bits/version.def | 10 +
libstdc++-v3/include/bits/version.h | 10 +
libstdc++-v3/include/std/hazard_pointer | 44 +
.../testsuite/30_threads/hazard_pointer/1.cc | 28 +
.../30_threads/hazard_pointer/concurrent.cc | 406 ++++++
.../30_threads/hazard_pointer/ctor.cc | 102 ++
.../hazard_pointer/custom_deleter.cc | 126 ++
.../30_threads/hazard_pointer/empty.cc | 105 ++
.../30_threads/hazard_pointer/layout.cc | 85 ++
.../hazard_pointer/make_hazard_pointer.cc | 84 ++
.../30_threads/hazard_pointer/move_assign.cc | 91 ++
.../hazard_pointer/nodiscard_neg.cc | 58 +
.../30_threads/hazard_pointer/noexcept.cc | 56 +
.../30_threads/hazard_pointer/protect.cc | 96 ++
.../30_threads/hazard_pointer/protect_neg.cc | 43 +
.../hazard_pointer/reset_protection.cc | 116 ++
.../30_threads/hazard_pointer/retire.cc | 119 ++
.../30_threads/hazard_pointer/retire_neg.cc | 39 +
.../hazard_pointer/retire_no_alloc.cc | 213 ++++
.../hazard_pointer/retire_virtual_neg.cc | 40 +
.../30_threads/hazard_pointer/swap.cc | 133 ++
.../30_threads/hazard_pointer/thread_exit.cc | 98 ++
.../30_threads/hazard_pointer/try_protect.cc | 132 ++
.../hazard_pointer/type_constraints.cc | 56 +
.../30_threads/hazard_pointer/version.cc | 29 +
28 files changed, 3412 insertions(+)
create mode 100644 libstdc++-v3/include/bits/hazard_ptr.h
create mode 100644 libstdc++-v3/include/std/hazard_pointer
create mode 100644 libstdc++-v3/testsuite/30_threads/hazard_pointer/1.cc
create mode 100644 libstdc++-v3/testsuite/30_threads/hazard_pointer/concurrent.cc
create mode 100644 libstdc++-v3/testsuite/30_threads/hazard_pointer/ctor.cc
create mode 100644 libstdc++-v3/testsuite/30_threads/hazard_pointer/custom_deleter.cc
create mode 100644 libstdc++-v3/testsuite/30_threads/hazard_pointer/empty.cc
create mode 100644 libstdc++-v3/testsuite/30_threads/hazard_pointer/layout.cc
create mode 100644 libstdc++-v3/testsuite/30_threads/hazard_pointer/make_hazard_pointer.cc
create mode 100644 libstdc++-v3/testsuite/30_threads/hazard_pointer/move_assign.cc
create mode 100644 libstdc++-v3/testsuite/30_threads/hazard_pointer/nodiscard_neg.cc
create mode 100644 libstdc++-v3/testsuite/30_threads/hazard_pointer/noexcept.cc
create mode 100644 libstdc++-v3/testsuite/30_threads/hazard_pointer/protect.cc
create mode 100644 libstdc++-v3/testsuite/30_threads/hazard_pointer/protect_neg.cc
create mode 100644 libstdc++-v3/testsuite/30_threads/hazard_pointer/reset_protection.cc
create mode 100644 libstdc++-v3/testsuite/30_threads/hazard_pointer/retire.cc
create mode 100644 libstdc++-v3/testsuite/30_threads/hazard_pointer/retire_neg.cc
create mode 100644 libstdc++-v3/testsuite/30_threads/hazard_pointer/retire_no_alloc.cc
create mode 100644 libstdc++-v3/testsuite/30_threads/hazard_pointer/retire_virtual_neg.cc
create mode 100644 libstdc++-v3/testsuite/30_threads/hazard_pointer/swap.cc
create mode 100644 libstdc++-v3/testsuite/30_threads/hazard_pointer/thread_exit.cc
create mode 100644 libstdc++-v3/testsuite/30_threads/hazard_pointer/try_protect.cc
create mode 100644 libstdc++-v3/testsuite/30_threads/hazard_pointer/type_constraints.cc
create mode 100644 libstdc++-v3/testsuite/30_threads/hazard_pointer/version.cc
--
2.54.0