| // |
| // Copyright 2021 The ANGLE Project Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| // |
| // CLRefPointer.h: A non-owning intrinsic reference counting smart pointer for CL objects. |
| |
| #ifndef LIBANGLE_CLREFPOINTER_H_ |
| #define LIBANGLE_CLREFPOINTER_H_ |
| |
| #include <algorithm> |
| |
| namespace cl |
| { |
| |
| template <typename T> |
| class RefPointer |
| { |
| public: |
| RefPointer() noexcept : mCLObject(nullptr) {} |
| |
| explicit RefPointer(T *object) noexcept : mCLObject(object) |
| { |
| if (mCLObject != nullptr) |
| { |
| mCLObject->retain(); |
| } |
| } |
| ~RefPointer() |
| { |
| if (mCLObject != nullptr && mCLObject->release()) |
| { |
| delete mCLObject; |
| } |
| } |
| |
| RefPointer(std::nullptr_t) noexcept : mCLObject(nullptr) {} |
| RefPointer &operator=(std::nullptr_t) |
| { |
| reset(); |
| return *this; |
| } |
| |
| RefPointer(RefPointer &&other) noexcept : mCLObject(nullptr) { this->swap(other); } |
| RefPointer &operator=(RefPointer &&other) |
| { |
| this->swap(other); |
| return *this; |
| } |
| |
| RefPointer(const RefPointer<T> &other) : mCLObject(other.mCLObject) |
| { |
| if (mCLObject != nullptr) |
| { |
| mCLObject->retain(); |
| } |
| } |
| RefPointer &operator=(const RefPointer<T> &other) |
| { |
| if (this != &other) |
| { |
| reset(); |
| mCLObject = other.mCLObject; |
| if (mCLObject != nullptr) |
| { |
| mCLObject->retain(); |
| } |
| } |
| return *this; |
| } |
| |
| T *operator->() const { return mCLObject; } |
| T &operator*() const { return *mCLObject; } |
| |
| T *get() const { return mCLObject; } |
| explicit operator bool() const { return mCLObject != nullptr; } |
| |
| T *release() noexcept |
| { |
| T *const object = mCLObject; |
| mCLObject = nullptr; |
| return object; |
| } |
| |
| void swap(RefPointer &other) noexcept { std::swap(mCLObject, other.mCLObject); } |
| |
| void reset() |
| { |
| if (mCLObject != nullptr) |
| { |
| T *const object = release(); |
| object->release(); |
| } |
| } |
| |
| private: |
| T *mCLObject; |
| }; |
| |
| template <typename T> |
| void swap(RefPointer<T> &left, RefPointer<T> &right) |
| { |
| left.swap(right); |
| } |
| |
| template <typename T> |
| bool operator==(const RefPointer<T> &ptr, nullptr_t) noexcept |
| { |
| return ptr.get() == nullptr; |
| } |
| |
| template <typename T> |
| bool operator==(nullptr_t, const RefPointer<T> &ptr) noexcept |
| { |
| return ptr.get() == nullptr; |
| } |
| |
| template <typename T> |
| bool operator!=(const RefPointer<T> &ptr, nullptr_t) noexcept |
| { |
| return ptr.get() != nullptr; |
| } |
| |
| template <typename T> |
| bool operator!=(nullptr_t, const RefPointer<T> &ptr) noexcept |
| { |
| return ptr.get() != nullptr; |
| } |
| |
| template <typename T, typename U> |
| bool operator==(const RefPointer<T> &left, const RefPointer<U> &right) noexcept |
| { |
| return left.get() == right.get(); |
| } |
| |
| template <typename T, typename U> |
| bool operator!=(const RefPointer<T> &left, const RefPointer<U> &right) noexcept |
| { |
| return left.get() != right.get(); |
| } |
| |
| template <typename T, typename U> |
| bool operator==(const RefPointer<T> &left, const U *right) noexcept |
| { |
| return left.get() == right; |
| } |
| |
| template <typename T, typename U> |
| bool operator==(const T *left, const RefPointer<U> &right) noexcept |
| { |
| return left == right.get(); |
| } |
| |
| template <typename T, typename U> |
| bool operator!=(const RefPointer<T> &left, const U *right) noexcept |
| { |
| return left.get() != right; |
| } |
| |
| template <typename T, typename U> |
| bool operator!=(const T *left, const RefPointer<U> &right) noexcept |
| { |
| return left != right.get(); |
| } |
| |
| } // namespace cl |
| |
| #endif // LIBANGLE_CLREFPOINTER_H_ |