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.
16 /* -*- Mode: C++; tab-width: 2; c-basic-offset: 2; indent-tabs-mode: nil -*- */
21 #include <folly/experimental/TLRefCount.h>
25 template <typename T, typename RefCount>
26 class ReadMostlyMainPtr;
27 template <typename T, typename RefCount>
28 class ReadMostlyWeakPtr;
29 template <typename T, typename RefCount>
30 class ReadMostlySharedPtr;
31 template <typename RefCount>
32 class ReadMostlyMainPtrDeleter;
34 using DefaultRefCount = TLRefCount;
38 template <typename T, typename RefCount = DefaultRefCount>
39 class ReadMostlySharedPtrCore {
45 std::shared_ptr<T> getShared() {
63 auto value = ++weakCount_;
68 if (--weakCount_ == 0) {
73 size_t useCount() const {
77 ~ReadMostlySharedPtrCore() noexcept {
79 assert(*weakCount_ == 0);
83 friend class ReadMostlyMainPtr<T, RefCount>;
84 friend class ReadMostlyMainPtrDeleter<RefCount>;
86 explicit ReadMostlySharedPtrCore(std::shared_ptr<T> ptr) :
88 ptr_(std::move(ptr)) {
94 std::shared_ptr<T> ptr_;
99 template <typename T, typename RefCount = DefaultRefCount>
100 class ReadMostlyMainPtr {
102 ReadMostlyMainPtr() {
105 explicit ReadMostlyMainPtr(std::shared_ptr<T> ptr) {
106 reset(std::move(ptr));
109 ReadMostlyMainPtr(const ReadMostlyMainPtr&) = delete;
110 ReadMostlyMainPtr& operator=(const ReadMostlyMainPtr&) = delete;
112 ReadMostlyMainPtr(ReadMostlyMainPtr&& other) noexcept {
113 *this = std::move(other);
116 ReadMostlyMainPtr& operator=(ReadMostlyMainPtr&& other) noexcept {
117 std::swap(impl_, other.impl_);
122 bool operator==(const ReadMostlyMainPtr<T, RefCount>& other) const {
123 return get() == other.get();
126 bool operator==(T* other) const {
127 return get() == other;
130 bool operator==(const ReadMostlySharedPtr<T, RefCount>& other) const {
131 return get() == other.get();
134 ~ReadMostlyMainPtr() noexcept {
138 void reset() noexcept {
140 impl_->count_.useGlobal();
141 impl_->weakCount_.useGlobal();
147 void reset(std::shared_ptr<T> ptr) {
150 impl_ = new detail::ReadMostlySharedPtrCore<T, RefCount>(std::move(ptr));
156 return impl_->ptrRaw_;
162 std::shared_ptr<T> getStdShared() const {
164 return impl_->getShared();
170 T& operator*() const {
174 T* operator->() const {
178 ReadMostlySharedPtr<T, RefCount> getShared() const {
179 return ReadMostlySharedPtr<T, RefCount>(*this);
182 explicit operator bool() const {
183 return impl_ != nullptr;
187 friend class ReadMostlyWeakPtr<T, RefCount>;
188 friend class ReadMostlySharedPtr<T, RefCount>;
189 friend class ReadMostlyMainPtrDeleter<RefCount>;
191 detail::ReadMostlySharedPtrCore<T, RefCount>* impl_{nullptr};
194 template <typename T, typename RefCount = DefaultRefCount>
195 class ReadMostlyWeakPtr {
197 ReadMostlyWeakPtr() {}
199 explicit ReadMostlyWeakPtr(const ReadMostlyMainPtr<T, RefCount>& mainPtr) {
200 reset(mainPtr.impl_);
203 explicit ReadMostlyWeakPtr(const ReadMostlySharedPtr<T, RefCount>& ptr) {
207 ReadMostlyWeakPtr(const ReadMostlyWeakPtr& other) {
211 ReadMostlyWeakPtr& operator=(const ReadMostlyWeakPtr& other) {
216 ReadMostlyWeakPtr& operator=(const ReadMostlyMainPtr<T, RefCount>& mainPtr) {
217 reset(mainPtr.impl_);
221 ReadMostlyWeakPtr(ReadMostlyWeakPtr&& other) noexcept {
225 ReadMostlyWeakPtr& operator=(ReadMostlyWeakPtr&& other) noexcept {
226 std::swap(impl_, other.impl_);
230 ~ReadMostlyWeakPtr() noexcept {
234 ReadMostlySharedPtr<T, RefCount> lock() {
235 return ReadMostlySharedPtr<T, RefCount>(*this);
239 friend class ReadMostlySharedPtr<T, RefCount>;
241 void reset(detail::ReadMostlySharedPtrCore<T, RefCount>* impl) {
251 detail::ReadMostlySharedPtrCore<T, RefCount>* impl_{nullptr};
254 template <typename T, typename RefCount = DefaultRefCount>
255 class ReadMostlySharedPtr {
257 ReadMostlySharedPtr() {}
259 explicit ReadMostlySharedPtr(const ReadMostlyWeakPtr<T, RefCount>& weakPtr) {
260 reset(weakPtr.impl_);
263 // Generally, this shouldn't be used.
264 explicit ReadMostlySharedPtr(const ReadMostlyMainPtr<T, RefCount>& mainPtr) {
265 reset(mainPtr.impl_);
268 ReadMostlySharedPtr(const ReadMostlySharedPtr& other) {
272 ReadMostlySharedPtr& operator=(const ReadMostlySharedPtr& other) {
277 ReadMostlySharedPtr& operator=(const ReadMostlyWeakPtr<T, RefCount>& other) {
282 ReadMostlySharedPtr& operator=(const ReadMostlyMainPtr<T, RefCount>& other) {
287 ReadMostlySharedPtr(ReadMostlySharedPtr&& other) noexcept {
288 *this = std::move(other);
291 ~ReadMostlySharedPtr() noexcept {
295 ReadMostlySharedPtr& operator=(ReadMostlySharedPtr&& other) noexcept {
296 std::swap(ptr_, other.ptr_);
297 std::swap(impl_, other.impl_);
301 bool operator==(const ReadMostlyMainPtr<T, RefCount>& other) const {
302 return get() == other.get();
305 bool operator==(T* other) const {
306 return get() == other;
309 bool operator==(const ReadMostlySharedPtr<T, RefCount>& other) const {
310 return get() == other.get();
321 std::shared_ptr<T> getStdShared() const {
323 return impl_->getShared();
329 T& operator*() const {
333 T* operator->() const {
337 size_t use_count() const {
338 return impl_->useCount();
341 bool unique() const {
342 return use_count() == 1;
345 explicit operator bool() const {
346 return impl_ != nullptr;
350 friend class ReadMostlyWeakPtr<T, RefCount>;
352 void reset(detail::ReadMostlySharedPtrCore<T, RefCount>* impl) {
359 if (impl && impl->incref()) {
366 detail::ReadMostlySharedPtrCore<T, RefCount>* impl_{nullptr};
370 * This can be used to destroy multiple ReadMostlyMainPtrs at once.
372 template <typename RefCount = DefaultRefCount>
373 class ReadMostlyMainPtrDeleter {
375 ~ReadMostlyMainPtrDeleter() noexcept {
376 RefCount::useGlobal(refCounts_);
377 for (auto& decref : decrefs_) {
382 template <typename T>
383 void add(ReadMostlyMainPtr<T, RefCount> ptr) noexcept {
388 refCounts_.push_back(&ptr.impl_->count_);
389 refCounts_.push_back(&ptr.impl_->weakCount_);
390 decrefs_.push_back([impl = ptr.impl_] { impl->decref(); });
395 std::vector<RefCount*> refCounts_;
396 std::vector<folly::Function<void()>> decrefs_;
399 template <typename T, typename RefCount>
400 inline bool operator==(
401 const ReadMostlyMainPtr<T, RefCount>& ptr,
403 return ptr.get() == nullptr;
406 template <typename T, typename RefCount>
407 inline bool operator==(
409 const ReadMostlyMainPtr<T, RefCount>& ptr) {
410 return ptr.get() == nullptr;
413 template <typename T, typename RefCount>
414 inline bool operator==(
415 const ReadMostlySharedPtr<T, RefCount>& ptr,
417 return ptr.get() == nullptr;
420 template <typename T, typename RefCount>
421 inline bool operator==(
423 const ReadMostlySharedPtr<T, RefCount>& ptr) {
424 return ptr.get() == nullptr;
427 template <typename T, typename RefCount>
428 inline bool operator!=(
429 const ReadMostlyMainPtr<T, RefCount>& ptr,
431 return !(ptr == nullptr);
434 template <typename T, typename RefCount>
435 inline bool operator!=(
437 const ReadMostlyMainPtr<T, RefCount>& ptr) {
438 return !(ptr == nullptr);
441 template <typename T, typename RefCount>
442 inline bool operator!=(
443 const ReadMostlySharedPtr<T, RefCount>& ptr,
445 return !(ptr == nullptr);
448 template <typename T, typename RefCount>
449 inline bool operator!=(
451 const ReadMostlySharedPtr<T, RefCount>& ptr) {
452 return !(ptr == nullptr);