2 * Copyright 2016 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;
32 using DefaultRefCount = TLRefCount;
36 template <typename T, typename RefCount = DefaultRefCount>
37 class ReadMostlySharedPtrCore {
43 std::shared_ptr<T> getShared() {
61 auto value = ++weakCount_;
66 if (--weakCount_ == 0) {
71 size_t useCount() const {
75 ~ReadMostlySharedPtrCore() noexcept {
77 assert(*weakCount_ == 0);
81 friend class ReadMostlyMainPtr<T, RefCount>;
83 explicit ReadMostlySharedPtrCore(std::shared_ptr<T> ptr) :
85 ptr_(std::move(ptr)) {
91 std::shared_ptr<T> ptr_;
96 template <typename T, typename RefCount = DefaultRefCount>
97 class ReadMostlyMainPtr {
102 explicit ReadMostlyMainPtr(std::shared_ptr<T> ptr) {
103 reset(std::move(ptr));
106 ReadMostlyMainPtr(const ReadMostlyMainPtr&) = delete;
107 ReadMostlyMainPtr& operator=(const ReadMostlyMainPtr&) = delete;
109 ReadMostlyMainPtr(ReadMostlyMainPtr&& other) noexcept {
110 *this = std::move(other);
113 ReadMostlyMainPtr& operator=(ReadMostlyMainPtr&& other) noexcept {
114 std::swap(impl_, other.impl_);
119 bool operator==(const ReadMostlyMainPtr<T, RefCount>& other) const {
120 return get() == other.get();
123 bool operator==(T* other) const {
124 return get() == other;
127 bool operator==(const ReadMostlySharedPtr<T, RefCount>& other) const {
128 return get() == other.get();
131 ~ReadMostlyMainPtr() noexcept {
135 void reset() noexcept {
137 impl_->count_.useGlobal();
138 impl_->weakCount_.useGlobal();
144 void reset(std::shared_ptr<T> ptr) {
147 impl_ = new detail::ReadMostlySharedPtrCore<T, RefCount>(std::move(ptr));
153 return impl_->ptrRaw_;
159 std::shared_ptr<T> getStdShared() {
167 T& operator*() const {
171 T* operator->() const {
175 ReadMostlySharedPtr<T, RefCount> getShared() const {
176 return ReadMostlySharedPtr<T, RefCount>(*this);
179 explicit operator bool() const {
180 return impl_ != nullptr;
184 friend class ReadMostlyWeakPtr<T, RefCount>;
185 friend class ReadMostlySharedPtr<T, RefCount>;
187 detail::ReadMostlySharedPtrCore<T, RefCount>* impl_{nullptr};
190 template <typename T, typename RefCount = DefaultRefCount>
191 class ReadMostlyWeakPtr {
193 ReadMostlyWeakPtr() {}
195 explicit ReadMostlyWeakPtr(const ReadMostlyMainPtr<T, RefCount>& mainPtr) {
196 reset(mainPtr.impl_);
199 explicit ReadMostlyWeakPtr(const ReadMostlySharedPtr<T, RefCount>& ptr) {
203 ReadMostlyWeakPtr(const ReadMostlyWeakPtr& other) {
207 ReadMostlyWeakPtr& operator=(const ReadMostlyWeakPtr& other) {
212 ReadMostlyWeakPtr& operator=(const ReadMostlyMainPtr<T, RefCount>& mainPtr) {
213 reset(mainPtr.impl_);
217 ReadMostlyWeakPtr(ReadMostlyWeakPtr&& other) noexcept {
221 ReadMostlyWeakPtr& operator=(ReadMostlyWeakPtr&& other) noexcept {
222 std::swap(impl_, other.impl_);
226 ~ReadMostlyWeakPtr() noexcept {
230 ReadMostlySharedPtr<T, RefCount> lock() {
231 return ReadMostlySharedPtr<T, RefCount>(*this);
235 friend class ReadMostlySharedPtr<T, RefCount>;
237 void reset(detail::ReadMostlySharedPtrCore<T, RefCount>* impl) {
247 detail::ReadMostlySharedPtrCore<T, RefCount>* impl_{nullptr};
250 template <typename T, typename RefCount = DefaultRefCount>
251 class ReadMostlySharedPtr {
253 ReadMostlySharedPtr() {}
255 explicit ReadMostlySharedPtr(const ReadMostlyWeakPtr<T, RefCount>& weakPtr) {
256 reset(weakPtr.impl_);
259 // Generally, this shouldn't be used.
260 explicit ReadMostlySharedPtr(const ReadMostlyMainPtr<T, RefCount>& mainPtr) {
261 reset(mainPtr.impl_);
264 ReadMostlySharedPtr(const ReadMostlySharedPtr& other) {
268 ReadMostlySharedPtr& operator=(const ReadMostlySharedPtr& other) {
273 ReadMostlySharedPtr& operator=(const ReadMostlyWeakPtr<T, RefCount>& other) {
278 ReadMostlySharedPtr& operator=(const ReadMostlyMainPtr<T, RefCount>& other) {
283 ReadMostlySharedPtr(ReadMostlySharedPtr&& other) noexcept {
284 *this = std::move(other);
287 ~ReadMostlySharedPtr() noexcept {
291 ReadMostlySharedPtr& operator=(ReadMostlySharedPtr&& other) noexcept {
292 std::swap(ptr_, other.ptr_);
293 std::swap(impl_, other.impl_);
297 bool operator==(const ReadMostlyMainPtr<T, RefCount>& other) const {
298 return get() == other.get();
301 bool operator==(T* other) const {
302 return get() == other;
305 bool operator==(const ReadMostlySharedPtr<T, RefCount>& other) const {
306 return get() == other.get();
317 std::shared_ptr<T> getStdShared() const {
325 T& operator*() const {
329 T* operator->() const {
333 size_t use_count() const {
334 return impl_->useCount();
337 bool unique() const {
338 return use_count() == 1;
341 explicit operator bool() const {
342 return impl_ != nullptr;
346 friend class ReadMostlyWeakPtr<T, RefCount>;
348 void reset(detail::ReadMostlySharedPtrCore<T, RefCount>* impl) {
355 if (impl && impl->incref()) {
362 detail::ReadMostlySharedPtrCore<T, RefCount>* impl_{nullptr};