1 /* 2 * Copyright (c) 2024 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #ifndef API_BASE_CONTAINERS_REFCNT_PTR_H 17 #define API_BASE_CONTAINERS_REFCNT_PTR_H 18 19 #include <base/containers/type_traits.h> 20 #include <base/namespace.h> 21 BASE_BEGIN_NAMESPACE()22BASE_BEGIN_NAMESPACE() 23 template<class T> 24 class refcnt_ptr { 25 public: 26 using pointer = BASE_NS::remove_reference_t<T>*; 27 using element_type = T; 28 29 constexpr refcnt_ptr() noexcept {} 30 31 constexpr refcnt_ptr(nullptr_t) noexcept {} 32 33 explicit constexpr refcnt_ptr(pointer ptr) noexcept : ptr_(ptr) 34 { 35 if (ptr) { 36 ptr->Ref(); 37 } 38 } 39 40 refcnt_ptr(const refcnt_ptr& ptr) : refcnt_ptr(ptr.get()) {} 41 42 template<class U> 43 refcnt_ptr(const refcnt_ptr<U>& ptr) : refcnt_ptr(static_cast<T*>(ptr.get())) 44 {} 45 46 refcnt_ptr(refcnt_ptr&& ptr) noexcept : ptr_(exchange(ptr.ptr_, nullptr)) {} 47 48 template<class U> 49 refcnt_ptr(refcnt_ptr<U>&& ptr) noexcept : ptr_(static_cast<T*>(ptr.release())) 50 {} 51 52 ~refcnt_ptr() 53 { 54 if (ptr_) { 55 ptr_->Unref(); 56 } 57 } 58 59 pointer get() const noexcept 60 { 61 return ptr_; 62 } 63 64 pointer release() noexcept 65 { 66 pointer res = ptr_; 67 ptr_ = nullptr; 68 return res; 69 } 70 71 void reset(pointer ptr = pointer()) noexcept 72 { 73 if (ptr_ != ptr) { 74 pointer old_ptr = ptr_; 75 ptr_ = ptr; 76 if (ptr_) { 77 ptr_->Ref(); 78 } 79 if (old_ptr) { 80 old_ptr->Unref(); 81 } 82 } 83 } 84 85 refcnt_ptr& operator=(nullptr_t) noexcept 86 { 87 reset(); 88 return *this; 89 } 90 91 refcnt_ptr& operator=(const refcnt_ptr& r) noexcept 92 { 93 reset(r.get()); 94 return *this; 95 } 96 97 template<class U> 98 refcnt_ptr& operator=(const refcnt_ptr<U>& r) noexcept 99 { 100 reset(r.get()); 101 return *this; 102 } 103 104 refcnt_ptr& operator=(refcnt_ptr&& r) noexcept 105 { 106 reset(); 107 ptr_ = exchange(r.ptr_, nullptr); 108 return *this; 109 } 110 111 template<class U> 112 refcnt_ptr& operator=(refcnt_ptr<U>&& r) noexcept 113 { 114 reset(); 115 ptr_ = r.release(); 116 return *this; 117 } 118 119 void swap(refcnt_ptr& other) noexcept 120 { 121 ptr_ = exchange(other.ptr_, ptr_); 122 } 123 124 explicit operator bool() const noexcept 125 { 126 return (ptr_ != nullptr); 127 } 128 129 bool operator==(const refcnt_ptr& other) const noexcept 130 { 131 return (ptr_ == other.ptr_); 132 } 133 134 bool operator!=(const refcnt_ptr& other) const noexcept 135 { 136 return (ptr_ != other.ptr_); 137 } 138 139 pointer operator->() const noexcept 140 { 141 return ptr_; 142 } 143 144 typename BASE_NS::add_lvalue_reference<T>::type operator*() const 145 { 146 return *ptr_; 147 } 148 149 bool operator!=(nullptr_t) const noexcept 150 { 151 return ptr_ != nullptr; 152 } 153 154 bool operator==(nullptr_t) const noexcept 155 { 156 return ptr_ == nullptr; 157 } 158 159 protected: 160 pointer ptr_ { nullptr }; 161 }; 162 BASE_END_NAMESPACE() 163 164 #endif // API_BASE_CONTAINERS_REFCNT_PTR_H 165