2 * Copyright 2015 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/RCURefCount.h>
22 #include <folly/experimental/TLRefCount.h>
26 template <typename T, typename RefCount>
27 class ReadMostlyMainPtr;
28 template <typename T, typename RefCount>
29 class ReadMostlyWeakPtr;
30 template <typename T, typename RefCount>
31 class ReadMostlySharedPtr;
33 using DefaultRefCount = TLRefCount;
37 template <typename T, typename RefCount = DefaultRefCount>
38 class ReadMostlySharedPtrCore {
44 std::shared_ptr<T> getShared() {
62 auto value = ++weakCount_;
67 if (--weakCount_ == 0) {
72 size_t useCount() const {
76 ~ReadMostlySharedPtrCore() noexcept {
78 assert(*weakCount_ == 0);
82 friend class ReadMostlyMainPtr<T, RefCount>;
84 explicit ReadMostlySharedPtrCore(std::shared_ptr<T> ptr) :
86 ptr_(std::move(ptr)) {
92 std::shared_ptr<T> ptr_;
97 template <typename T, typename RefCount = DefaultRefCount>
98 class ReadMostlyMainPtr {
100 ReadMostlyMainPtr() {
103 explicit ReadMostlyMainPtr(std::shared_ptr<T> ptr) {
104 reset(std::move(ptr));
107 ReadMostlyMainPtr(const ReadMostlyMainPtr&) = delete;
108 ReadMostlyMainPtr& operator=(const ReadMostlyMainPtr&) = delete;
110 ReadMostlyMainPtr(ReadMostlyMainPtr&& other) noexcept {
111 *this = std::move(other);
114 ReadMostlyMainPtr& operator=(ReadMostlyMainPtr&& other) noexcept {
115 std::swap(impl_, other.impl_);
120 bool operator==(const ReadMostlyMainPtr<T, RefCount>& other) const {
121 return get() == other.get();
124 bool operator==(T* other) const {
125 return get() == other;
128 bool operator==(const ReadMostlySharedPtr<T, RefCount>& other) const {
129 return get() == other.get();
132 ~ReadMostlyMainPtr() noexcept {
136 void reset() noexcept {
138 impl_->count_.useGlobal();
139 impl_->weakCount_.useGlobal();
145 void reset(std::shared_ptr<T> ptr) {
148 impl_ = new detail::ReadMostlySharedPtrCore<T, RefCount>(std::move(ptr));
154 return impl_->ptrRaw_;
160 std::shared_ptr<T> getStdShared() {
168 T& operator*() const {
172 T* operator->() const {
176 ReadMostlySharedPtr<T, RefCount> getShared() const {
177 return ReadMostlySharedPtr<T, RefCount>(*this);
180 explicit operator bool() const {
181 return impl_ != nullptr;
185 friend class ReadMostlyWeakPtr<T, RefCount>;
186 friend class ReadMostlySharedPtr<T, RefCount>;
188 detail::ReadMostlySharedPtrCore<T, RefCount>* impl_{nullptr};
191 template <typename T, typename RefCount = DefaultRefCount>
192 class ReadMostlyWeakPtr {
194 ReadMostlyWeakPtr() {}
196 explicit ReadMostlyWeakPtr(const ReadMostlyMainPtr<T, RefCount>& mainPtr) {
197 reset(mainPtr.impl_);
200 ReadMostlyWeakPtr(const ReadMostlyWeakPtr& other) {
204 ReadMostlyWeakPtr& operator=(const ReadMostlyWeakPtr& other) {
209 ReadMostlyWeakPtr(ReadMostlyWeakPtr&& other) noexcept {
213 ReadMostlyWeakPtr& operator=(ReadMostlyWeakPtr&& other) noexcept {
214 std::swap(impl_, other.impl_);
218 ~ReadMostlyWeakPtr() noexcept {
222 ReadMostlySharedPtr<T, RefCount> lock() {
223 return ReadMostlySharedPtr<T, RefCount>(*this);
227 friend class ReadMostlySharedPtr<T, RefCount>;
229 void reset(detail::ReadMostlySharedPtrCore<T, RefCount>* impl) {
239 detail::ReadMostlySharedPtrCore<T, RefCount>* impl_{nullptr};
242 template <typename T, typename RefCount = DefaultRefCount>
243 class ReadMostlySharedPtr {
245 ReadMostlySharedPtr() {}
247 explicit ReadMostlySharedPtr(const ReadMostlyWeakPtr<T, RefCount>& weakPtr) {
248 reset(weakPtr.impl_);
251 // Generally, this shouldn't be used.
252 explicit ReadMostlySharedPtr(const ReadMostlyMainPtr<T, RefCount>& mainPtr) {
253 reset(mainPtr.impl_);
256 ReadMostlySharedPtr(const ReadMostlySharedPtr& other) {
260 ReadMostlySharedPtr& operator=(const ReadMostlySharedPtr& other) {
265 ReadMostlySharedPtr& operator=(const ReadMostlyWeakPtr<T, RefCount>& other) {
270 ReadMostlySharedPtr& operator=(const ReadMostlyMainPtr<T, RefCount>& other) {
275 ReadMostlySharedPtr(ReadMostlySharedPtr&& other) noexcept {
276 *this = std::move(other);
279 ~ReadMostlySharedPtr() noexcept {
283 ReadMostlySharedPtr& operator=(ReadMostlySharedPtr&& other) noexcept {
284 std::swap(ptr_, other.ptr_);
285 std::swap(impl_, other.impl_);
289 bool operator==(const ReadMostlyMainPtr<T, RefCount>& other) const {
290 return get() == other.get();
293 bool operator==(T* other) const {
294 return get() == other;
297 bool operator==(const ReadMostlySharedPtr<T, RefCount>& other) const {
298 return get() == other.get();
309 std::shared_ptr<T> getStdShared() const {
317 T& operator*() const {
321 T* operator->() const {
325 size_t use_count() const {
326 return impl_->useCount();
329 bool unique() const {
330 return use_count() == 1;
333 explicit operator bool() const {
334 return impl_ != nullptr;
338 void reset(detail::ReadMostlySharedPtrCore<T, RefCount>* impl) {
345 if (impl && impl->incref()) {
352 detail::ReadMostlySharedPtrCore<T, RefCount>* impl_{nullptr};