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.
21 /* Stand-in for C++17 std::pmr::memory_resource */
22 #include <folly/experimental/hazptr/memory_resource.h>
27 /** hazptr_rec: Private class that contains hazard pointers. */
30 /** hazptr_obj: Private class for objects protected by hazard pointers. */
33 /** hazptr_obj_base: Base template for objects protected by hazard pointers. */
34 template <typename T, typename Deleter>
35 class hazptr_obj_base;
37 /** hazptr_domain: Class of hazard pointer domains. Each domain manages a set
38 * of hazard pointers and a set of retired objects. */
41 constexpr explicit hazptr_domain(
42 memory_resource* = get_default_resource()) noexcept;
45 hazptr_domain(const hazptr_domain&) = delete;
46 hazptr_domain(hazptr_domain&&) = delete;
47 hazptr_domain& operator=(const hazptr_domain&) = delete;
48 hazptr_domain& operator=(hazptr_domain&&) = delete;
51 friend class hazptr_holder;
52 template <typename, typename>
53 friend class hazptr_obj_base;
54 friend class hazptr_priv;
57 std::atomic<hazptr_rec*> hazptrs_ = {nullptr};
58 std::atomic<hazptr_obj*> retired_ = {nullptr};
59 std::atomic<int> hcount_ = {0};
60 std::atomic<int> rcount_ = {0};
62 void objRetire(hazptr_obj*);
63 hazptr_rec* hazptrAcquire();
64 void hazptrRelease(hazptr_rec*) noexcept;
65 int pushRetired(hazptr_obj* head, hazptr_obj* tail, int count);
66 bool reachedThreshold(int rcount);
67 void tryBulkReclaim();
71 /** Get the default hazptr_domain */
72 hazptr_domain& default_hazptr_domain();
74 /** Definition of hazptr_obj */
76 friend class hazptr_domain;
77 template <typename, typename>
78 friend class hazptr_obj_base;
79 friend class hazptr_priv;
81 void (*reclaim_)(hazptr_obj*);
83 const void* getObjPtr() const;
86 /** Definition of hazptr_obj_base */
87 template <typename T, typename D = std::default_delete<T>>
88 class hazptr_obj_base : public hazptr_obj {
90 /* Retire a removed object and pass the responsibility for
91 * reclaiming it to the hazptr library */
92 void retire(hazptr_domain& domain = default_hazptr_domain(), D reclaim = {});
98 /** hazptr_holder: Class for automatic acquisition and release of
99 * hazard pointers, and interface for hazard pointer operations. */
100 class hazptr_holder {
102 /* Constructor automatically acquires a hazard pointer. */
103 explicit hazptr_holder(hazptr_domain& domain = default_hazptr_domain());
104 /* Construct an empty hazptr_holder. */
105 // Note: This diverges from the proposal in P0233R4
106 explicit hazptr_holder(std::nullptr_t);
108 /* Destructor automatically clears and releases the owned hazard pointer. */
111 hazptr_holder(const hazptr_holder&) = delete;
112 hazptr_holder& operator=(const hazptr_holder&) = delete;
113 // Note: This diverges from the proposal in P0233R4 which disallows
114 // move constructor and assignment operator.
115 hazptr_holder(hazptr_holder&&) noexcept;
116 hazptr_holder& operator=(hazptr_holder&&) noexcept;
118 /** Hazard pointer operations */
119 /* Returns a protected pointer from the source */
120 template <typename T>
121 T* get_protected(const std::atomic<T*>& src) noexcept;
122 /* Returns a protected pointer from the source, filtering
123 the protected pointer through function Func. Useful for
124 stealing bits of the pointer word */
125 template <typename T, typename Func>
126 T* get_protected(const std::atomic<T*>& src, Func f) noexcept;
127 /* Return true if successful in protecting ptr if src == ptr after
128 * setting the hazard pointer. Otherwise sets ptr to src. */
129 template <typename T>
130 bool try_protect(T*& ptr, const std::atomic<T*>& src) noexcept;
131 /* Return true if successful in protecting ptr if src == ptr after
132 * setting the hazard pointer, filtering the pointer through Func.
133 * Otherwise sets ptr to src. */
134 template <typename T, typename Func>
135 bool try_protect(T*& ptr, const std::atomic<T*>& src, Func f) noexcept;
136 /* Set the hazard pointer to ptr */
137 template <typename T>
138 void reset(const T* ptr) noexcept;
139 /* Set the hazard pointer to nullptr */
140 void reset(std::nullptr_t = nullptr) noexcept;
142 /* Swap ownership of hazard pointers between hazptr_holder-s. */
143 /* Note: The owned hazard pointers remain unmodified during the swap
144 * and continue to protect the respective objects that they were
145 * protecting before the swap, if any. */
146 void swap(hazptr_holder&) noexcept;
149 hazptr_domain* domain_;
153 void swap(hazptr_holder&, hazptr_holder&) noexcept;
155 } // namespace hazptr
158 #include "hazptr-impl.h"