1 /* 2 * Copyright (C) 2018 The Android Open Source Project 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 17 #ifndef INCLUDE_PERFETTO_TRACE_PROCESSOR_REF_COUNTED_H_ 18 #define INCLUDE_PERFETTO_TRACE_PROCESSOR_REF_COUNTED_H_ 19 20 #include <stddef.h> 21 #include <stdint.h> 22 23 #include <memory> 24 25 #include "perfetto/base/logging.h" 26 27 // A non-thread-safe refcounted implementation. 28 // Unlike std::shared_ptr The target class needs to explicitly derive 29 // RefCounted. 30 31 // Usage: 32 // class MyRefcountedThing : public RefCounted {}; 33 // ... 34 // RefPtr<MyRefcountedThing> shareable_ptr(new MyRefcountedThing()); 35 // auto copy = shareable_ptr; 36 37 namespace perfetto { 38 namespace trace_processor { 39 40 // The base class that refcounted classes should inherit. 41 class RefCounted { 42 public: 43 RefCounted() = default; 44 RefCounted(RefCounted&&) noexcept = default; 45 RefCounted& operator=(RefCounted&&) noexcept = default; 46 RefCounted(const RefCounted&) = delete; 47 RefCounted& operator=(const RefCounted&) = delete; 48 49 private: 50 template <typename T> 51 friend class RefPtr; 52 AddRef()53 void AddRef() const { 54 PERFETTO_DCHECK(refcount_ >= 0); 55 ++refcount_; 56 } Release()57 bool Release() const { 58 PERFETTO_DCHECK(refcount_ > 0); 59 return --refcount_ == 0; 60 } 61 62 mutable intptr_t refcount_ = 0; 63 }; 64 65 // The RAII smart-pointer. 66 template <typename T> 67 class RefPtr { 68 public: 69 static_assert(std::is_base_of<RefCounted, T>::value, 70 "T must be a descendant of RefCounted"); 71 72 // Adopt a newly created object. RefPtr()73 RefPtr() : ptr_(nullptr) {} RefPtr(T * ptr)74 explicit RefPtr(T* ptr) : ptr_(ptr) { 75 if (ptr_) 76 ptr_->AddRef(); 77 } 78 ~RefPtr()79 ~RefPtr() { reset(); } 80 reset()81 void reset() { 82 auto* old_ptr = ptr_; 83 ptr_ = nullptr; 84 if (old_ptr && old_ptr->Release()) 85 delete old_ptr; 86 } 87 88 // This case is really the move-assignment operator=(&&). reset(T * new_obj)89 void reset(T* new_obj) { *this = RefPtr<T>(new_obj); } 90 91 // Move operators. RefPtr(RefPtr && move_from)92 RefPtr(RefPtr&& move_from) noexcept { 93 ptr_ = move_from.ptr_; 94 move_from.ptr_ = nullptr; 95 } 96 97 RefPtr& operator=(RefPtr&& move_from) noexcept { 98 this->~RefPtr(); 99 new (this) RefPtr(std::move(move_from)); 100 return *this; 101 } 102 103 // Copy operators. RefPtr(const RefPtr & copy_from)104 RefPtr(const RefPtr& copy_from) { 105 ptr_ = copy_from.ptr_; 106 if (ptr_) 107 ptr_->AddRef(); 108 } 109 110 RefPtr& operator=(const RefPtr& copy_from) { 111 if (this != ©_from) { 112 this->~RefPtr(); 113 new (this) RefPtr(copy_from); 114 } 115 return *this; 116 } 117 118 template <typename U> 119 bool operator==(const RefPtr<U>& rhs) const { 120 return ptr_ == rhs.ptr_; 121 } 122 get()123 T* get() const { return ptr_; } 124 T* operator->() const { return ptr_; } 125 T& operator*() const { return *ptr_; } 126 explicit operator bool() const { return ptr_ != nullptr; } 127 128 private: 129 T* ptr_ = nullptr; 130 }; 131 132 } // namespace trace_processor 133 } // namespace perfetto 134 135 #endif // INCLUDE_PERFETTO_TRACE_PROCESSOR_REF_COUNTED_H_ 136