proxygen
HazptrObj.h
Go to the documentation of this file.
1 /*
2  * Copyright 2018-present Facebook, Inc.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16 #pragma once
17 
19 
20 #include <folly/CPortability.h>
21 #include <folly/Portability.h>
22 
23 #include <glog/logging.h>
24 
25 #include <atomic>
26 #include <memory>
27 
31 
32 namespace folly {
33 
39 template <template <typename> class Atom>
40 class hazptr_obj {
42 
43  template <template <typename> class>
44  friend class hazptr_domain;
45  template <typename, template <typename> class, typename>
46  friend class hazptr_obj_base;
47  template <typename, template <typename> class, typename>
48  friend class hazptr_obj_base_linked;
49  template <template <typename> class>
50  friend class hazptr_obj_list;
51  template <template <typename> class>
52  friend class hazptr_priv;
53 
56 
57  public:
59  /* All constructors set next_ to this in order to catch misuse bugs
60  such as double retire. */
61 
62  hazptr_obj() noexcept : next_(this) {}
63 
64  hazptr_obj(const hazptr_obj<Atom>&) noexcept : next_(this) {}
65 
66  hazptr_obj(hazptr_obj<Atom>&&) noexcept : next_(this) {}
67 
70  return *this;
71  }
72 
75  return *this;
76  }
77 
78  private:
79  friend class hazptr_domain<Atom>;
80  template <typename, template <typename> class, typename>
81  friend class hazptr_obj_base;
82  template <typename, template <typename> class, typename>
84  friend class hazptr_priv<Atom>;
85 
87  return next_;
88  }
89 
91  next_ = obj;
92  }
93 
95  return reclaim_;
96  }
97 
98  const void* raw_ptr() const {
99  return this;
100  }
101 
103  // Only for catching misuse bugs like double retire
104  if (next_ != this) {
106  }
107  }
108 
110 #if FOLLY_HAZPTR_THR_LOCAL
111  if (&domain == &default_hazptr_domain<Atom>() && !domain.shutdown_) {
112  hazptr_priv_tls<Atom>().push(this);
113  return;
114  }
115 #endif
116  hazptr_obj_list<Atom> l(this);
117  hazptr_domain_push_retired(l, true, domain);
118  }
119 
121  CHECK_EQ(next_, this);
122  }
123 }; // hazptr_obj
124 
130 template <template <typename> class Atom>
131 class hazptr_obj_list {
134  int count_;
135 
136  public:
137  hazptr_obj_list() noexcept : head_(nullptr), tail_(nullptr), count_(0) {}
138 
140  : head_(obj), tail_(obj), count_(1) {}
141 
142  explicit hazptr_obj_list(
143  hazptr_obj<Atom>* head,
144  hazptr_obj<Atom>* tail,
145  int count) noexcept
146  : head_(head), tail_(tail), count_(count) {}
147 
149  return head_;
150  }
151 
153  return tail_;
154  }
155 
156  int count() {
157  return count_;
158  }
159 
160  void push(hazptr_obj<Atom>* obj) {
161  obj->set_next(head_);
162  head_ = obj;
163  if (tail_ == nullptr) {
164  tail_ = obj;
165  }
166  ++count_;
167  }
168 
170  if (l.count() == 0) {
171  return;
172  }
173  if (count() == 0) {
174  head_ = l.head();
175  } else {
176  tail_->set_next(l.head());
177  }
178  tail_ = l.tail();
179  count_ += l.count();
180  l.clear();
181  }
182 
183  void clear() {
184  head_ = nullptr;
185  tail_ = nullptr;
186  count_ = 0;
187  }
188 }; // hazptr_obj_list
189 
195 template <typename T, typename D>
196 class hazptr_deleter {
198 
199  public:
200  void set_deleter(D d = {}) {
201  deleter_ = std::move(d);
202  }
203 
204  void delete_obj(T* p) {
205  deleter_(p);
206  }
207 };
208 
209 template <typename T>
210 class hazptr_deleter<T, std::default_delete<T>> {
211  public:
212  void set_deleter(std::default_delete<T> = {}) {}
213 
214  void delete_obj(T* p) {
215  delete p;
216  }
217 };
218 
224 template <typename T, template <typename> class Atom, typename D>
225 class hazptr_obj_base : public hazptr_obj<Atom>, public hazptr_deleter<T, D> {
226  public:
227  /* Retire a removed object and pass the responsibility for
228  * reclaiming it to the hazptr library */
229  void retire(
230  D deleter = {},
231  hazptr_domain<Atom>& domain = default_hazptr_domain<Atom>()) {
232  pre_retire(std::move(deleter));
233  set_reclaim();
234  this->push_to_retired(domain); // defined in hazptr_obj
235  }
236 
237  void retire(hazptr_domain<Atom>& domain) {
238  retire({}, domain);
239  }
240 
241  private:
242  void pre_retire(D deleter) {
243  this->pre_retire_check(); // defined in hazptr_obj
244  this->set_deleter(std::move(deleter));
245  }
246 
247  void set_reclaim() {
249  auto hobp = static_cast<hazptr_obj_base<T, Atom, D>*>(p);
250  auto obj = static_cast<T*>(hobp);
251  hobp->delete_obj(obj);
252  };
253  }
254 }; // hazptr_obj_base
255 
256 } // namespace folly
void splice(hazptr_obj_list< Atom > &l)
Definition: HazptrObj.h:169
hazptr_obj< Atom > & operator=(hazptr_obj< Atom > &&) noexcept
Definition: HazptrObj.h:74
hazptr_obj(hazptr_obj< Atom > &&) noexcept
Definition: HazptrObj.h:66
ReclaimFnPtr reclaim() noexcept
Definition: HazptrObj.h:94
ReclaimFnPtr reclaim_
Definition: HazptrObj.h:54
hazptr_obj_list(hazptr_obj< Atom > *head, hazptr_obj< Atom > *tail, int count) noexcept
Definition: HazptrObj.h:142
void push(hazptr_obj< Atom > *obj)
Definition: HazptrObj.h:160
hazptr_obj< Atom > * tail()
Definition: HazptrObj.h:152
void pre_retire(D deleter)
Definition: HazptrObj.h:242
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
void retire(D deleter={}, hazptr_domain< Atom > &domain=default_hazptr_domain< Atom >())
Definition: HazptrObj.h:229
hazptr_obj< Atom > * head_
Definition: HazptrObj.h:132
STL namespace.
void set_deleter(std::default_delete< T >={})
Definition: HazptrObj.h:212
hazptr_obj(const hazptr_obj< Atom > &) noexcept
Definition: HazptrObj.h:64
folly::std T
—— Concurrent Priority Queue Implementation ——
Definition: AtomicBitSet.h:29
requires E e noexcept(noexcept(s.error(std::move(e))))
hazptr_obj< Atom > * head()
Definition: HazptrObj.h:148
#define FOLLY_NOINLINE
Definition: CPortability.h:142
FOLLY_NOINLINE void pre_retire_check_fail() noexcept
Definition: HazptrObj.h:120
#define D(name, bit)
Definition: CpuId.h:145
#define Atom
void(*)(hazptr_obj< Atom > *, hazptr_obj_list< Atom > &) ReclaimFnPtr
Definition: HazptrObj.h:41
hazptr_obj_list() noexcept
Definition: HazptrObj.h:137
void delete_obj(T *p)
Definition: HazptrObj.h:204
int * count
hazptr_obj< Atom > * tail_
Definition: HazptrObj.h:133
void pre_retire_check() noexcept
Definition: HazptrObj.h:102
void set_next(hazptr_obj *obj) noexcept
Definition: HazptrObj.h:90
hazptr_obj< Atom > & operator=(const hazptr_obj< Atom > &) noexcept
Definition: HazptrObj.h:69
const
Definition: upload.py:398
void retire(hazptr_domain< Atom > &domain)
Definition: HazptrObj.h:237
const void * raw_ptr() const
Definition: HazptrObj.h:98
hazptr_obj< Atom > * next() const noexcept
Definition: HazptrObj.h:86
void push_to_retired(hazptr_domain< Atom > &domain)
Definition: HazptrObj.h:109
void set_deleter(D d={})
Definition: HazptrObj.h:200
hazptr_obj< Atom > * next_
Definition: HazptrObj.h:55
hazptr_obj_list(hazptr_obj< Atom > *obj) noexcept
Definition: HazptrObj.h:139
void hazptr_domain_push_retired(hazptr_obj_list< Atom > &l, bool check=true, hazptr_domain< Atom > &domain=default_hazptr_domain< Atom >()) noexcept
Definition: HazptrDomain.h:369
friend class hazptr_obj_base_refcounted
Definition: HazptrObj.h:83
hazptr_obj() noexcept
Definition: HazptrObj.h:62