1 /* 2 * Copyright (C) 2023 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 <cstddef> 20 21 #include <base/containers/type_traits.h> 22 #include <base/namespace.h> 23 BASE_BEGIN_NAMESPACE()24BASE_BEGIN_NAMESPACE() 25 template<class T> 26 class refcnt_ptr { 27 public: 28 using pointer = BASE_NS::remove_reference_t<T>*; 29 using element_type = T; 30 31 constexpr refcnt_ptr() noexcept {} 32 33 constexpr refcnt_ptr(nullptr_t) noexcept {} 34 35 explicit constexpr refcnt_ptr(pointer ptr) noexcept : ptr_(ptr) 36 { 37 if (ptr) { 38 ptr->Ref(); 39 } 40 } 41 42 refcnt_ptr(const refcnt_ptr& ptr) : refcnt_ptr(ptr.get()) {} 43 44 template<class U> 45 refcnt_ptr(const refcnt_ptr<U>& ptr) : refcnt_ptr(static_cast<T*>(ptr.get())) 46 {} 47 48 refcnt_ptr(refcnt_ptr&& ptr) noexcept : ptr_(exchange(ptr.ptr_, nullptr)) {} 49 50 template<class U> 51 refcnt_ptr(refcnt_ptr<U>&& ptr) noexcept : ptr_(static_cast<T*>(ptr.release())) 52 {} 53 54 ~refcnt_ptr() 55 { 56 if (ptr_) { 57 ptr_->Unref(); 58 } 59 } 60 61 pointer get() const noexcept 62 { 63 return ptr_; 64 } 65 66 pointer release() noexcept 67 { 68 pointer res = ptr_; 69 ptr_ = nullptr; 70 return res; 71 } 72 73 void reset(pointer ptr = pointer()) noexcept 74 { 75 if (ptr_ != ptr) { 76 pointer old_ptr = ptr_; 77 ptr_ = ptr; 78 if (ptr_) { 79 ptr_->Ref(); 80 } 81 if (old_ptr) { 82 old_ptr->Unref(); 83 } 84 } 85 } 86 87 refcnt_ptr& operator=(nullptr_t) noexcept 88 { 89 reset(); 90 return *this; 91 } 92 93 refcnt_ptr& operator=(const refcnt_ptr& r) noexcept 94 { 95 reset(r.get()); 96 return *this; 97 } 98 99 template<class U> 100 refcnt_ptr& operator=(const refcnt_ptr<U>& r) noexcept 101 { 102 reset(r.get()); 103 return *this; 104 } 105 106 refcnt_ptr& operator=(refcnt_ptr&& r) noexcept 107 { 108 reset(); 109 ptr_ = exchange(r.ptr_, nullptr); 110 return *this; 111 } 112 113 template<class U> 114 refcnt_ptr& operator=(refcnt_ptr<U>&& r) noexcept 115 { 116 reset(); 117 ptr_ = r.release(); 118 return *this; 119 } 120 121 void swap(refcnt_ptr& other) noexcept 122 { 123 ptr_ = exchange(other.ptr_, ptr_); 124 } 125 126 explicit operator bool() const noexcept 127 { 128 return (ptr_ != nullptr); 129 } 130 131 bool operator==(const refcnt_ptr& other) const noexcept 132 { 133 return (ptr_ == other.ptr_); 134 } 135 136 bool operator!=(const refcnt_ptr& other) const noexcept 137 { 138 return (ptr_ != other.ptr_); 139 } 140 141 pointer operator->() const noexcept 142 { 143 return ptr_; 144 } 145 146 typename BASE_NS::add_lvalue_reference<T>::type operator*() const 147 { 148 return *ptr_; 149 } 150 151 bool operator!=(nullptr_t) const noexcept 152 { 153 return ptr_ != nullptr; 154 } 155 156 bool operator==(nullptr_t) const noexcept 157 { 158 return ptr_ == nullptr; 159 } 160 161 protected: 162 pointer ptr_ { nullptr }; 163 }; 164 BASE_END_NAMESPACE() 165 166 #endif // API_BASE_CONTAINERS_REFCNT_PTR_H 167