[libcxx-commits] [libcxx] [libcxx] P0718R2: Implementation of std::atomic<shared_ptr<T>> and std::atomic<weak_ptr<T>> (PR #194215)

Hristo Hristov via libcxx-commits libcxx-commits at lists.llvm.org
Sat May 2 04:55:29 PDT 2026


================
@@ -0,0 +1,102 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Shared fixtures for libc++ tests under util.smartptr/atomic/{shared,weak}/:
+// heterogeneous value types (built-in, standard library, and user-defined).
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LIBCXX_TEST_STD_UTILITIES_MEMORY_UTIL_SMARTPTR_ATOMIC_ATOMIC_SMART_PTR_TEST_TYPES_H
+#define LIBCXX_TEST_STD_UTILITIES_MEMORY_UTIL_SMARTPTR_ATOMIC_ATOMIC_SMART_PTR_TEST_TYPES_H
+
+#include <cstdint>
+#include <memory>
+#include <string>
+
+namespace libcxx_atomic_smart_ptr_test {
+
+// --- User-defined and semi-random scalar-like types ---------------------------------
+
+struct TrackedPod {
+  std::uint32_t gen{};
+  std::int64_t salt{};
+  friend constexpr bool operator==(TrackedPod lhs, TrackedPod rhs) noexcept {
+    return lhs.gen == rhs.gen && lhs.salt == rhs.salt;
+  }
+};
+
+class Handle {
+  double coeff_{};
+
+public:
+  explicit Handle(double c = 0.0) : coeff_(c) {}
+  double coeff() const noexcept { return coeff_; }
+  friend bool operator==(Handle const& lhs, Handle const& rhs) noexcept { return lhs.coeff_ == rhs.coeff_; }
+};
+
+enum class Flag : std::uint16_t { Off = 0, Stale = 4099, On = 60000 };
+
+// --- Distinct shared states for compare/exchange style tests ------------------------
+
+template <class T>
+struct SpValues;
+
+template <>
+struct SpValues<int> {
+  static std::shared_ptr<int> state_a() { return std::make_shared<int>(-90210); }
+  static std::shared_ptr<int> state_b() { return std::make_shared<int>(404); }
+  static std::shared_ptr<int> state_c() { return std::make_shared<int>(7331); }
+};
+
+template <>
+struct SpValues<double> {
+  static std::shared_ptr<double> state_a() { return std::make_shared<double>(1.4142135623730951); }
+  static std::shared_ptr<double> state_b() { return std::make_shared<double>(2.7182818284590452); }
+  static std::shared_ptr<double> state_c() { return std::make_shared<double>(3.1415926535897932); }
+};
+
+template <>
+struct SpValues<std::string> {
+  static std::shared_ptr<std::string> state_a() { return std::make_shared<std::string>("kappa"); }
+  static std::shared_ptr<std::string> state_b() { return std::make_shared<std::string>("lambda"); }
+  static std::shared_ptr<std::string> state_c() { return std::make_shared<std::string>("mu"); }
+};
+
+template <>
+struct SpValues<TrackedPod> {
+  static std::shared_ptr<TrackedPod> state_a() { return std::make_shared<TrackedPod>(TrackedPod{3u, -77L}); }
+  static std::shared_ptr<TrackedPod> state_b() { return std::make_shared<TrackedPod>(TrackedPod{101u, 1L << 20}); }
+  static std::shared_ptr<TrackedPod> state_c() { return std::make_shared<TrackedPod>(TrackedPod{255u, -1L}); }
+};
+
+template <>
+struct SpValues<Handle> {
+  static std::shared_ptr<Handle> state_a() { return std::make_shared<Handle>(0.125); }
+  static std::shared_ptr<Handle> state_b() { return std::make_shared<Handle>(-4096.5); }
+  static std::shared_ptr<Handle> state_c() { return std::make_shared<Handle>(8192.25); }
+};
+
+template <>
+struct SpValues<Flag> {
+  static std::shared_ptr<Flag> state_a() { return std::make_shared<Flag>(Flag::Off); }
+  static std::shared_ptr<Flag> state_b() { return std::make_shared<Flag>(Flag::Stale); }
+  static std::shared_ptr<Flag> state_c() { return std::make_shared<Flag>(Flag::On); }
+};
+
+} // namespace libcxx_atomic_smart_ptr_test
+
+// Instantiate the same runtime coverage for every value type.
+#define LIBCXX_ATOMIC_SP_FOR_ALL_RUNTIME_TYPES(M)                                                                              \
+  M(int)                                                                                                                       \
+  M(double)                                                                                                                    \
+  M(std::string)                                                                                                               \
+  M(libcxx_atomic_smart_ptr_test::TrackedPod)                                                                                  \
+  M(libcxx_atomic_smart_ptr_test::Handle)                                                                                      \
+  M(libcxx_atomic_smart_ptr_test::Flag)
----------------
H-G-Hristov wrote:

Wouldn't a function object be a bit better, similar to what's implemented in: https://github.com/llvm/llvm-project/blob/482d0f01f680c01342d6c9feacd3e693b7f75167/libcxx/test/support/atomic_helpers.h#L219

FYI Please also note we use the following pattern to test runtime and constexpr:

```C++ 
constexpr bool test() { 
  ...
  return true;
}

int main(...) {
  test();
  static_assert(test());
}
```
see https://github.com/llvm/llvm-project/pull/98765 https://github.com/llvm/llvm-project/pull/98756


https://github.com/llvm/llvm-project/pull/194215


More information about the libcxx-commits mailing list