/proc/self/cwd/src/common/utils/intrusive_ptr.h
Line | Count | Source (jump to first uncovered line) |
1 | | //----------------------------------------------------------------------------- |
2 | | // Copyright 2022 Google LLC |
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 | | // https://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 | | #ifndef SRC_COMMON_UTILS_INTRUSIVE_PTR_H_ |
17 | | #define SRC_COMMON_UTILS_INTRUSIVE_PTR_H_ |
18 | | |
19 | | #include "src/common/utils/ref_counted.h" |
20 | | |
21 | | namespace raksha { |
22 | | |
23 | | // An implementation of reference counted ptr where the reference count is |
24 | | // embedded in the object itself (i.e., intrusive). This is mostly based on the |
25 | | // implementation of boost::intrusive_ptr. |
26 | | template <typename T> |
27 | | class intrusive_ptr { |
28 | | public: |
29 | | // Factory function for creating instances of intrusive_ptr. It might be |
30 | | // more convenient and succint to use the global make_intrusive_ptr below. |
31 | | template <typename... Args> |
32 | | static intrusive_ptr<T> create(Args&&... a) { |
33 | | return intrusive_ptr<T>(new T(std::forward<Args>(a)...)); |
34 | | } |
35 | | |
36 | | intrusive_ptr() : ptr_(nullptr) {} |
37 | 124k | intrusive_ptr(T* ptr) : ptr_(Retain(ptr)) {} |
38 | 124k | intrusive_ptr(const intrusive_ptr<T>& other) : ptr_(Retain(other.ptr_)) {} |
39 | | // There is no need to adjust count on a move. |
40 | 124k | intrusive_ptr(intrusive_ptr<T>&& other) : ptr_(other.ptr_) { |
41 | 124k | other.ptr_ = nullptr; |
42 | 124k | } |
43 | | |
44 | | template <class X, |
45 | | std::enable_if_t<std::is_convertible<X*, T*>::value, bool> = true> |
46 | | intrusive_ptr(const intrusive_ptr<X>& other) : ptr_(Retain(other.get())) {} |
47 | | |
48 | 373k | ~intrusive_ptr() { Release(ptr_); } |
49 | | |
50 | | intrusive_ptr<T>& operator=(intrusive_ptr<T> other) { |
51 | | // We are using the copy-and-swap idiom for assignment. |
52 | | // Argument `other` should be passed by value. |
53 | | this->Swap(other); |
54 | | return *this; |
55 | | } |
56 | | |
57 | 0 | T& operator*() const { |
58 | 0 | CHECK(ptr_ != nullptr) << "Dereferencing a nullptr!"; |
59 | 0 | return *ptr_; |
60 | 0 | } |
61 | | |
62 | 0 | T* operator->() const { return ptr_; } Unexecuted instantiation: raksha::intrusive_ptr<raksha::ir::AttributeBase const>::operator->() const Unexecuted instantiation: raksha::intrusive_ptr<raksha::ir::types::TypeBase>::operator->() const |
63 | 0 | T* get() const { return ptr_; } Unexecuted instantiation: raksha::intrusive_ptr<raksha::ir::AttributeBase const>::get() const Unexecuted instantiation: raksha::intrusive_ptr<raksha::ir::types::TypeBase>::get() const |
64 | | explicit operator bool() const { return ptr_ != nullptr; } |
65 | | |
66 | | private: |
67 | | void Swap(intrusive_ptr<T>& other) { |
68 | | T* tmp = other.ptr_; |
69 | | other.ptr_ = ptr_; |
70 | | ptr_ = tmp; |
71 | | } |
72 | | |
73 | 249k | T* Retain(T* p) { |
74 | 249k | if (p) { |
75 | 249k | RefCountManager<T>::Retain(p); |
76 | 249k | } |
77 | 249k | return p; |
78 | 249k | } raksha::intrusive_ptr<raksha::ir::types::TypeBase>::Retain(raksha::ir::types::TypeBase*) Line | Count | Source | 73 | 249k | T* Retain(T* p) { | 74 | 249k | if (p) { | 75 | 249k | RefCountManager<T>::Retain(p); | 76 | 249k | } | 77 | 249k | return p; | 78 | 249k | } |
Unexecuted instantiation: raksha::intrusive_ptr<raksha::ir::AttributeBase const>::Retain(raksha::ir::AttributeBase const*) |
79 | | |
80 | 373k | void Release(T* p) { |
81 | 373k | if (p) { |
82 | 249k | RefCountManager<T>::Release(p); |
83 | 249k | } |
84 | 373k | } raksha::intrusive_ptr<raksha::ir::types::TypeBase>::Release(raksha::ir::types::TypeBase*) Line | Count | Source | 80 | 373k | void Release(T* p) { | 81 | 373k | if (p) { | 82 | 249k | RefCountManager<T>::Release(p); | 83 | 249k | } | 84 | 373k | } |
Unexecuted instantiation: raksha::intrusive_ptr<raksha::ir::AttributeBase const>::Release(raksha::ir::AttributeBase const*) |
85 | | |
86 | | T* ptr_; |
87 | | }; |
88 | | |
89 | | // Creates an intrusive_ptr by invoking the constructor of the underlying |
90 | | // type. |
91 | | template <typename T, typename... Args> |
92 | | inline intrusive_ptr<T> make_intrusive_ptr(Args&&... a) { |
93 | | return intrusive_ptr<T>::create(std::forward<Args>(a)...); |
94 | | } |
95 | | |
96 | | template <class T, class U> |
97 | 0 | bool operator==(const intrusive_ptr<T>& lhs, const intrusive_ptr<U>& rhs) { |
98 | 0 | return lhs.get() == rhs.get(); |
99 | 0 | } |
100 | | |
101 | | template <class T, class U> |
102 | | bool operator!=(const intrusive_ptr<T>& lhs, const intrusive_ptr<U>& rhs) { |
103 | | return !(lhs == rhs); |
104 | | } |
105 | | |
106 | | template <class T, class U> |
107 | | bool operator==(const intrusive_ptr<T>& lhs, U* rhs) { |
108 | | return lhs.get() == rhs; |
109 | | } |
110 | | |
111 | | template <class T, class U> |
112 | | bool operator!=(const intrusive_ptr<T>& lhs, U* rhs) { |
113 | | return !(lhs.get() == rhs); |
114 | | } |
115 | | |
116 | | template <class T, class U> |
117 | | bool operator==(T* lhs, const intrusive_ptr<U>& rhs) { |
118 | | return lhs == rhs.get(); |
119 | | } |
120 | | |
121 | | template <class T, class U> |
122 | | bool operator!=(T* lhs, const intrusive_ptr<U>& rhs) { |
123 | | return !(lhs == rhs.get()); |
124 | | } |
125 | | |
126 | | template <class T> |
127 | | bool operator==(std::nullptr_t, const intrusive_ptr<T>& rhs) { |
128 | | return !(rhs.get()); |
129 | | } |
130 | | |
131 | | template <class T> |
132 | | bool operator==(const intrusive_ptr<T>& lhs, std::nullptr_t rhs) { |
133 | | return rhs == lhs.get(); |
134 | | } |
135 | | |
136 | | template <class T> |
137 | | bool operator!=(std::nullptr_t lhs, const intrusive_ptr<T>& rhs) { |
138 | | return !(lhs == rhs.get()); |
139 | | } |
140 | | |
141 | | template <class T> |
142 | 0 | bool operator!=(const intrusive_ptr<T>& lhs, std::nullptr_t rhs) { |
143 | 0 | return !(lhs.get() == rhs); |
144 | 0 | } |
145 | | } // namespace raksha |
146 | | |
147 | | #endif // SRC_COMMON_UTILS_INTRUSIVE_PTR_H_ |