2 * Copyright 2017 Facebook, Inc.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
22 #include <type_traits>
24 /* Stand-in for C++17 std::pmr::memory_resource */
25 #include <folly/experimental/hazptr/memory_resource.h>
30 /** hazptr_rec: Private class that contains hazard pointers. */
33 /** hazptr_obj: Private class for objects protected by hazard pointers. */
36 /** hazptr_obj_base: Base template for objects protected by hazard pointers. */
37 template <typename T, typename Deleter>
38 class hazptr_obj_base;
40 /** hazptr_domain: Class of hazard pointer domains. Each domain manages a set
41 * of hazard pointers and a set of retired objects. */
44 constexpr explicit hazptr_domain(
45 memory_resource* = get_default_resource()) noexcept;
48 hazptr_domain(const hazptr_domain&) = delete;
49 hazptr_domain(hazptr_domain&&) = delete;
50 hazptr_domain& operator=(const hazptr_domain&) = delete;
51 hazptr_domain& operator=(hazptr_domain&&) = delete;
54 template <typename, typename>
55 friend class hazptr_obj_base;
57 friend class hazptr_owner;
60 std::atomic<hazptr_rec*> hazptrs_ = {nullptr};
61 std::atomic<hazptr_obj*> retired_ = {nullptr};
62 std::atomic<int> hcount_ = {0};
63 std::atomic<int> rcount_ = {0};
65 void objRetire(hazptr_obj*);
66 hazptr_rec* hazptrAcquire();
67 void hazptrRelease(hazptr_rec*) noexcept;
68 int pushRetired(hazptr_obj* head, hazptr_obj* tail, int count);
69 void tryBulkReclaim();
73 /** Get the default hazptr_domain */
74 hazptr_domain& default_hazptr_domain();
76 /** Definition of hazptr_obj */
78 friend class hazptr_domain;
79 template <typename, typename>
80 friend class hazptr_obj_base;
82 void (*reclaim_)(hazptr_obj*);
84 const void* getObjPtr() const;
87 /** Definition of hazptr_obj_base */
88 template <typename T, typename Deleter = std::default_delete<T>>
89 class hazptr_obj_base : public hazptr_obj {
91 /* Retire a removed object and pass the responsibility for
92 * reclaiming it to the hazptr library */
94 hazptr_domain& domain = default_hazptr_domain(),
95 Deleter reclaim = {});
101 /** hazptr_owner: Template for automatic acquisition and release of
102 * hazard pointers, and interface for hazard pointer operations. */
103 template <typename T> class hazptr_owner {
105 /* Constructor automatically acquires a hazard pointer. */
106 explicit hazptr_owner(hazptr_domain& domain = default_hazptr_domain());
107 /* Destructor automatically clears and releases the owned hazard pointer. */
110 /* Copy and move constructors and assignment operators are
111 * disallowed because:
112 * - Each hazptr_owner owns exactly one hazard pointer at any time.
113 * - Each hazard pointer may have up to one owner at any time. */
114 hazptr_owner(const hazptr_owner&) = delete;
115 hazptr_owner(hazptr_owner&&) = delete;
116 hazptr_owner& operator=(const hazptr_owner&) = delete;
117 hazptr_owner& operator=(hazptr_owner&&) = delete;
119 /** Hazard pointer operations */
120 /* Returns a protected pointer from the source */
121 template <typename A = std::atomic<T*>>
122 T* get_protected(const A& src) noexcept;
123 /* Return true if successful in protecting ptr if src == ptr after
124 * setting the hazard pointer. Otherwise sets ptr to src. */
125 template <typename A = std::atomic<T*>>
126 bool try_protect(T*& ptr, const A& src) noexcept;
127 /* Set the hazard pointer to ptr */
128 void set(const T* ptr) noexcept;
129 /* Clear the hazard pointer */
130 void clear() noexcept;
132 /* Swap ownership of hazard pointers between hazptr_owner-s. */
133 /* Note: The owned hazard pointers remain unmodified during the swap
134 * and continue to protect the respective objects that they were
135 * protecting before the swap, if any. */
136 void swap(hazptr_owner&) noexcept;
139 hazptr_domain* domain_;
143 template <typename T>
144 void swap(hazptr_owner<T>&, hazptr_owner<T>&) noexcept;
146 } // namespace hazptr
149 #include "hazptr-impl.h"