[libcxx-commits] [libcxx] [libc++] Implement P2545R4 Read-Copy Update (RCU) (PR #175451)
via libcxx-commits
libcxx-commits at lists.llvm.org
Sun Sep 13 02:58:31 PDT 2026
================
@@ -0,0 +1,118 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP___RCU_RCU_LIST_H
+#define _LIBCPP___RCU_RCU_LIST_H
+
+#include <__config>
+#include <__functional/function.h>
+#include <__rcu/rcu_domain.h>
+#include <atomic>
+
+#include "thread_local_container.h"
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+# pragma GCC system_header
+#endif
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+#if _LIBCPP_STD_VER >= 26 && _LIBCPP_HAS_THREADS && _LIBCPP_HAS_EXPERIMENTAL_RCU
+
+class rcu_thread_local_list_view;
+
+class rcu_singly_list_view {
+private:
+ __rcu_node* head_ = nullptr;
+ __rcu_node* tail_ = nullptr;
+
+public:
+ void splice_back(rcu_singly_list_view& other) noexcept {
+ if (other.head_ == nullptr) {
+ return;
+ }
+ if (head_ == nullptr) {
+ head_ = other.head_;
+ tail_ = other.tail_;
+ } else {
+ tail_->__next_ = other.head_;
+ tail_ = other.tail_;
+ }
+ other.head_ = nullptr;
+ other.tail_ = nullptr;
+ }
+
+ void splice_back(rcu_thread_local_list_view& __other) noexcept;
+
+ template <class Func>
+ void for_each(Func&& f) noexcept {
+ __rcu_node* current = head_;
+ while (current != nullptr) {
+ // __f could delete __current, so we need to get the next pointer first
+ auto __next = current->__next_;
+ f(current);
+ current = __next;
+ }
+ }
+};
+
+class rcu_thread_local_list_view {
+ struct alignas(2 * sizeof(void*)) thread_entry {
+ __rcu_node* head_ = nullptr;
+ __rcu_node* tail_ = nullptr;
+ };
+
+ using per_thread_entries = thread_local_container<thread_entry>;
+
+ friend class rcu_singly_list_view;
+
+public:
+ void push_front(__rcu_node* node) noexcept {
+ atomic_ref<thread_entry> entry_ref = per_thread_entries::get_current_thread_instance();
+ auto expected_entry = entry_ref.load(std::memory_order_relaxed);
+ auto original_next = node->__next_;
+ while (true) {
+ auto new_entry = [&] {
+ if (expected_entry.head_ == nullptr) {
+ return thread_entry{node, node};
+ } else {
+ node->__next_ = expected_entry.head_;
+ return thread_entry{node, expected_entry.tail_};
+ }
+ }();
+ if (entry_ref.compare_exchange_weak(
+ expected_entry, new_entry, std::memory_order_acq_rel, std::memory_order_relaxed)) {
+ break;
+ } else {
+ node->__next_ = original_next;
+ }
+ }
+ }
+};
+
+void rcu_singly_list_view::splice_back(rcu_thread_local_list_view& __other) noexcept {
----------------
huixie90 wrote:
I did some refactoring and let the list owns the `atomic` and removed the `atomic_ref` from the `thread_local_container`
https://github.com/llvm/llvm-project/pull/175451
More information about the libcxx-commits
mailing list