// // 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 namespace cl { template 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 &other) : mCLObject(other.mCLObject) { if (mCLObject != nullptr) { mCLObject->retain(); } } RefPointer &operator=(const RefPointer &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 void swap(RefPointer &left, RefPointer &right) { left.swap(right); } template bool operator==(const RefPointer &ptr, std::nullptr_t) noexcept { return ptr.get() == nullptr; } template bool operator==(std::nullptr_t, const RefPointer &ptr) noexcept { return ptr.get() == nullptr; } template bool operator!=(const RefPointer &ptr, std::nullptr_t) noexcept { return ptr.get() != nullptr; } template bool operator!=(std::nullptr_t, const RefPointer &ptr) noexcept { return ptr.get() != nullptr; } template bool operator==(const RefPointer &left, const RefPointer &right) noexcept { return left.get() == right.get(); } template bool operator!=(const RefPointer &left, const RefPointer &right) noexcept { return left.get() != right.get(); } template bool operator==(const RefPointer &left, const U *right) noexcept { return left.get() == right; } template bool operator==(const T *left, const RefPointer &right) noexcept { return left == right.get(); } template bool operator!=(const RefPointer &left, const U *right) noexcept { return left.get() != right; } template bool operator!=(const T *left, const RefPointer &right) noexcept { return left != right.get(); } } // namespace cl #endif // LIBANGLE_CLREFPOINTER_H_