Coverage Report

Created: 2023-12-11 06:17

/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_