proxygen
ReadMostlySharedPtr.h
Go to the documentation of this file.
1 /*
2  * Copyright 2015-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 /* -*- Mode: C++; tab-width: 2; c-basic-offset: 2; indent-tabs-mode: nil -*- */
17 #pragma once
18 
19 #include <atomic>
20 
22 
23 namespace folly {
24 
25 template <typename T, typename RefCount>
27 template <typename T, typename RefCount>
29 template <typename T, typename RefCount>
31 template <typename RefCount>
33 
35 
36 namespace detail {
37 
38 template <typename T, typename RefCount = DefaultRefCount>
40  public:
41  T* get() {
42  return ptrRaw_;
43  }
44 
45  std::shared_ptr<T> getShared() {
46  return ptr_;
47  }
48 
49  bool incref() {
50  return ++count_ > 0;
51  }
52 
53  void decref() {
54  if (--count_ == 0) {
55  ptrRaw_ = nullptr;
56  ptr_.reset();
57 
58  decrefWeak();
59  }
60  }
61 
62  void increfWeak() {
63  auto value = ++weakCount_;
64  DCHECK_GT(value, 0);
65  }
66 
67  void decrefWeak() {
68  if (--weakCount_ == 0) {
69  delete this;
70  }
71  }
72 
73  size_t useCount() const {
74  return *count_;
75  }
76 
78  assert(*count_ == 0);
79  assert(*weakCount_ == 0);
80  }
81 
82  private:
83  friend class ReadMostlyMainPtr<T, RefCount>;
84  friend class ReadMostlyMainPtrDeleter<RefCount>;
85 
86  explicit ReadMostlySharedPtrCore(std::shared_ptr<T> ptr)
87  : ptrRaw_(ptr.get()), ptr_(std::move(ptr)) {}
88 
90  RefCount count_;
91  RefCount weakCount_;
92  std::shared_ptr<T> ptr_;
93 };
94 
95 } // namespace detail
96 
97 template <typename T, typename RefCount = DefaultRefCount>
98 class ReadMostlyMainPtr {
99  public:
101 
102  explicit ReadMostlyMainPtr(std::shared_ptr<T> ptr) {
103  reset(std::move(ptr));
104  }
105 
106  ReadMostlyMainPtr(const ReadMostlyMainPtr&) = delete;
107  ReadMostlyMainPtr& operator=(const ReadMostlyMainPtr&) = delete;
108 
110  *this = std::move(other);
111  }
112 
114  std::swap(impl_, other.impl_);
115 
116  return *this;
117  }
118 
119  bool operator==(const ReadMostlyMainPtr<T, RefCount>& other) const {
120  return get() == other.get();
121  }
122 
123  bool operator==(T* other) const {
124  return get() == other;
125  }
126 
127  bool operator==(const ReadMostlySharedPtr<T, RefCount>& other) const {
128  return get() == other.get();
129  }
130 
132  reset();
133  }
134 
135  void reset() noexcept {
136  if (impl_) {
137  impl_->count_.useGlobal();
138  impl_->weakCount_.useGlobal();
139  impl_->decref();
140  impl_ = nullptr;
141  }
142  }
143 
144  void reset(std::shared_ptr<T> ptr) {
145  reset();
146  if (ptr) {
148  }
149  }
150 
151  T* get() const {
152  if (impl_) {
153  return impl_->ptrRaw_;
154  } else {
155  return nullptr;
156  }
157  }
158 
159  std::shared_ptr<T> getStdShared() const {
160  if (impl_) {
161  return impl_->getShared();
162  } else {
163  return {};
164  }
165  }
166 
167  T& operator*() const {
168  return *get();
169  }
170 
171  T* operator->() const {
172  return get();
173  }
174 
176  return ReadMostlySharedPtr<T, RefCount>(*this);
177  }
178 
179  explicit operator bool() const {
180  return impl_ != nullptr;
181  }
182 
183  private:
184  friend class ReadMostlyWeakPtr<T, RefCount>;
185  friend class ReadMostlySharedPtr<T, RefCount>;
186  friend class ReadMostlyMainPtrDeleter<RefCount>;
187 
189 };
190 
191 template <typename T, typename RefCount = DefaultRefCount>
192 class ReadMostlyWeakPtr {
193  public:
195 
197  reset(mainPtr.impl_);
198  }
199 
201  reset(ptr.impl_);
202  }
203 
205  *this = other;
206  }
207 
209  reset(other.impl_);
210  return *this;
211  }
212 
214  reset(mainPtr.impl_);
215  return *this;
216  }
217 
219  *this = other;
220  }
221 
223  std::swap(impl_, other.impl_);
224  return *this;
225  }
226 
228  reset(nullptr);
229  }
230 
232  return ReadMostlySharedPtr<T, RefCount>(*this);
233  }
234 
235  private:
236  friend class ReadMostlySharedPtr<T, RefCount>;
237 
239  if (impl_) {
240  impl_->decrefWeak();
241  }
242  impl_ = impl;
243  if (impl_) {
244  impl_->increfWeak();
245  }
246  }
247 
249 };
250 
251 template <typename T, typename RefCount = DefaultRefCount>
252 class ReadMostlySharedPtr {
253  public:
255 
257  reset(weakPtr.impl_);
258  }
259 
260  // Generally, this shouldn't be used.
262  reset(mainPtr.impl_);
263  }
264 
266  *this = other;
267  }
268 
270  reset(other.impl_);
271  return *this;
272  }
273 
275  reset(other.impl_);
276  return *this;
277  }
278 
280  reset(other.impl_);
281  return *this;
282  }
283 
285  *this = std::move(other);
286  }
287 
289  reset(nullptr);
290  }
291 
293  std::swap(ptr_, other.ptr_);
294  std::swap(impl_, other.impl_);
295  return *this;
296  }
297 
298  bool operator==(const ReadMostlyMainPtr<T, RefCount>& other) const {
299  return get() == other.get();
300  }
301 
302  bool operator==(T* other) const {
303  return get() == other;
304  }
305 
306  bool operator==(const ReadMostlySharedPtr<T, RefCount>& other) const {
307  return get() == other.get();
308  }
309 
310  void reset() {
311  reset(nullptr);
312  }
313 
314  T* get() const {
315  return ptr_;
316  }
317 
318  std::shared_ptr<T> getStdShared() const {
319  if (impl_) {
320  return impl_->getShared();
321  } else {
322  return {};
323  }
324  }
325 
326  T& operator*() const {
327  return *get();
328  }
329 
330  T* operator->() const {
331  return get();
332  }
333 
334  size_t use_count() const {
335  return impl_->useCount();
336  }
337 
338  bool unique() const {
339  return use_count() == 1;
340  }
341 
342  explicit operator bool() const {
343  return impl_ != nullptr;
344  }
345 
346  private:
347  friend class ReadMostlyWeakPtr<T, RefCount>;
348 
350  if (impl_) {
351  impl_->decref();
352  impl_ = nullptr;
353  ptr_ = nullptr;
354  }
355 
356  if (impl && impl->incref()) {
357  impl_ = impl;
358  ptr_ = impl->get();
359  }
360  }
361 
362  T* ptr_{nullptr};
364 };
365 
369 template <typename RefCount = DefaultRefCount>
371  public:
373  RefCount::useGlobal(refCounts_);
374  for (auto& decref : decrefs_) {
375  decref();
376  }
377  }
378 
379  template <typename T>
381  if (!ptr.impl_) {
382  return;
383  }
384 
385  refCounts_.push_back(&ptr.impl_->count_);
386  refCounts_.push_back(&ptr.impl_->weakCount_);
387  decrefs_.push_back([impl = ptr.impl_] { impl->decref(); });
388  ptr.impl_ = nullptr;
389  }
390 
391  private:
392  std::vector<RefCount*> refCounts_;
393  std::vector<folly::Function<void()>> decrefs_;
394 };
395 
396 template <typename T, typename RefCount>
397 inline bool operator==(
399  std::nullptr_t) {
400  return ptr.get() == nullptr;
401 }
402 
403 template <typename T, typename RefCount>
404 inline bool operator==(
405  std::nullptr_t,
407  return ptr.get() == nullptr;
408 }
409 
410 template <typename T, typename RefCount>
411 inline bool operator==(
413  std::nullptr_t) {
414  return ptr.get() == nullptr;
415 }
416 
417 template <typename T, typename RefCount>
418 inline bool operator==(
419  std::nullptr_t,
421  return ptr.get() == nullptr;
422 }
423 
424 template <typename T, typename RefCount>
425 inline bool operator!=(
427  std::nullptr_t) {
428  return !(ptr == nullptr);
429 }
430 
431 template <typename T, typename RefCount>
432 inline bool operator!=(
433  std::nullptr_t,
435  return !(ptr == nullptr);
436 }
437 
438 template <typename T, typename RefCount>
439 inline bool operator!=(
441  std::nullptr_t) {
442  return !(ptr == nullptr);
443 }
444 
445 template <typename T, typename RefCount>
446 inline bool operator!=(
447  std::nullptr_t,
449  return !(ptr == nullptr);
450 }
451 } // namespace folly
std::shared_ptr< T > getStdShared() const
void * ptr
void reset(std::shared_ptr< T > ptr)
ReadMostlySharedPtr< T, RefCount > getShared() const
ReadMostlyMainPtr(ReadMostlyMainPtr &&other) noexcept
bool operator==(const ReadMostlyMainPtr< T, RefCount > &other) const
ReadMostlySharedPtr & operator=(const ReadMostlyWeakPtr< T, RefCount > &other)
ReadMostlySharedPtr & operator=(const ReadMostlySharedPtr &other)
bool operator==(T *other) const
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
ReadMostlyWeakPtr & operator=(const ReadMostlyWeakPtr &other)
ReadMostlyWeakPtr(const ReadMostlySharedPtr< T, RefCount > &ptr)
std::shared_ptr< T > getStdShared() const
STL namespace.
ReadMostlySharedPtr & operator=(ReadMostlySharedPtr &&other) noexcept
ReadMostlyWeakPtr(ReadMostlyWeakPtr &&other) noexcept
folly::std T
—— Concurrent Priority Queue Implementation ——
Definition: AtomicBitSet.h:29
requires E e noexcept(noexcept(s.error(std::move(e))))
std::vector< folly::Function< void()> > decrefs_
ReadMostlyWeakPtr & operator=(ReadMostlyWeakPtr &&other) noexcept
void reset(detail::ReadMostlySharedPtrCore< T, RefCount > *impl)
ReadMostlySharedPtr & operator=(const ReadMostlyMainPtr< T, RefCount > &other)
bool operator!=(const Unexpected< Error > &lhs, const Unexpected< Error > &rhs)
Definition: Expected.h:766
ReadMostlyWeakPtr & operator=(const ReadMostlyMainPtr< T, RefCount > &mainPtr)
ReadMostlyWeakPtr(const ReadMostlyMainPtr< T, RefCount > &mainPtr)
std::vector< RefCount * > refCounts_
ReadMostlyMainPtr(std::shared_ptr< T > ptr)
detail::ReadMostlySharedPtrCore< T, RefCount > * impl_
ReadMostlySharedPtr(ReadMostlySharedPtr &&other) noexcept
void add(ReadMostlyMainPtr< T, RefCount > ptr) noexcept
detail::ReadMostlySharedPtrCore< T, RefCount > * impl_
ReadMostlySharedPtrCore(std::shared_ptr< T > ptr)
bool operator==(const ReadMostlySharedPtr< T, RefCount > &other) const
ReadMostlySharedPtr(const ReadMostlyMainPtr< T, RefCount > &mainPtr)
bool operator==(const Unexpected< Error > &lhs, const Unexpected< Error > &rhs)
Definition: Expected.h:758
ReadMostlySharedPtr< T, RefCount > lock()
ReadMostlySharedPtr(const ReadMostlyWeakPtr< T, RefCount > &weakPtr)
detail::ReadMostlySharedPtrCore< T, RefCount > * impl_
uint64_t value(const typename LockFreeRingBuffer< T, Atom >::Cursor &rbcursor)
ReadMostlySharedPtr(const ReadMostlySharedPtr &other)
void swap(SwapTrackingAlloc< T > &, SwapTrackingAlloc< T > &)
Definition: F14TestUtil.h:414
bool operator==(T *other) const
bool operator==(const ReadMostlyMainPtr< T, RefCount > &other) const
ReadMostlyWeakPtr(const ReadMostlyWeakPtr &other)
bool operator==(const ReadMostlySharedPtr< T, RefCount > &other) const
void reset(detail::ReadMostlySharedPtrCore< T, RefCount > *impl)
ReadMostlyMainPtr & operator=(ReadMostlyMainPtr &&other) noexcept