1 //
2 // Copyright 2021 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // CLRefPointer.h: A non-owning intrinsic reference counting smart pointer for CL objects.
7
8 #ifndef LIBANGLE_CLREFPOINTER_H_
9 #define LIBANGLE_CLREFPOINTER_H_
10
11 #include <algorithm>
12
13 namespace cl
14 {
15
16 template <typename T>
17 class RefPointer
18 {
19 public:
RefPointer()20 RefPointer() noexcept : mCLObject(nullptr) {}
21
RefPointer(T * object)22 explicit RefPointer(T *object) noexcept : mCLObject(object)
23 {
24 if (mCLObject != nullptr)
25 {
26 mCLObject->retain();
27 }
28 }
~RefPointer()29 ~RefPointer()
30 {
31 if (mCLObject != nullptr && mCLObject->release())
32 {
33 delete mCLObject;
34 }
35 }
36
RefPointer(std::nullptr_t)37 RefPointer(std::nullptr_t) noexcept : mCLObject(nullptr) {}
38 RefPointer &operator=(std::nullptr_t)
39 {
40 reset();
41 return *this;
42 }
43
RefPointer(RefPointer && other)44 RefPointer(RefPointer &&other) noexcept : mCLObject(nullptr) { this->swap(other); }
45 RefPointer &operator=(RefPointer &&other)
46 {
47 this->swap(other);
48 return *this;
49 }
50
RefPointer(const RefPointer<T> & other)51 RefPointer(const RefPointer<T> &other) : mCLObject(other.mCLObject)
52 {
53 if (mCLObject != nullptr)
54 {
55 mCLObject->retain();
56 }
57 }
58 RefPointer &operator=(const RefPointer<T> &other)
59 {
60 if (this != &other)
61 {
62 reset();
63 mCLObject = other.mCLObject;
64 if (mCLObject != nullptr)
65 {
66 mCLObject->retain();
67 }
68 }
69 return *this;
70 }
71
72 T *operator->() const { return mCLObject; }
73 T &operator*() const { return *mCLObject; }
74
get()75 T *get() const { return mCLObject; }
76 explicit operator bool() const { return mCLObject != nullptr; }
77
release()78 T *release() noexcept
79 {
80 T *const object = mCLObject;
81 mCLObject = nullptr;
82 return object;
83 }
84
swap(RefPointer & other)85 void swap(RefPointer &other) noexcept { std::swap(mCLObject, other.mCLObject); }
86
reset()87 void reset()
88 {
89 if (mCLObject != nullptr)
90 {
91 T *const object = release();
92 object->release();
93 }
94 }
95
96 private:
97 T *mCLObject;
98 };
99
100 template <typename T>
swap(RefPointer<T> & left,RefPointer<T> & right)101 void swap(RefPointer<T> &left, RefPointer<T> &right)
102 {
103 left.swap(right);
104 }
105
106 template <typename T>
107 bool operator==(const RefPointer<T> &ptr, nullptr_t) noexcept
108 {
109 return ptr.get() == nullptr;
110 }
111
112 template <typename T>
113 bool operator==(nullptr_t, const RefPointer<T> &ptr) noexcept
114 {
115 return ptr.get() == nullptr;
116 }
117
118 template <typename T>
119 bool operator!=(const RefPointer<T> &ptr, nullptr_t) noexcept
120 {
121 return ptr.get() != nullptr;
122 }
123
124 template <typename T>
125 bool operator!=(nullptr_t, const RefPointer<T> &ptr) noexcept
126 {
127 return ptr.get() != nullptr;
128 }
129
130 template <typename T, typename U>
131 bool operator==(const RefPointer<T> &left, const RefPointer<U> &right) noexcept
132 {
133 return left.get() == right.get();
134 }
135
136 template <typename T, typename U>
137 bool operator!=(const RefPointer<T> &left, const RefPointer<U> &right) noexcept
138 {
139 return left.get() != right.get();
140 }
141
142 template <typename T, typename U>
143 bool operator==(const RefPointer<T> &left, const U *right) noexcept
144 {
145 return left.get() == right;
146 }
147
148 template <typename T, typename U>
149 bool operator==(const T *left, const RefPointer<U> &right) noexcept
150 {
151 return left == right.get();
152 }
153
154 template <typename T, typename U>
155 bool operator!=(const RefPointer<T> &left, const U *right) noexcept
156 {
157 return left.get() != right;
158 }
159
160 template <typename T, typename U>
161 bool operator!=(const T *left, const RefPointer<U> &right) noexcept
162 {
163 return left != right.get();
164 }
165
166 } // namespace cl
167
168 #endif // LIBANGLE_CLREFPOINTER_H_
169