// // Copyright 2025 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. // // ObjCPtr.h: // Implements smart pointer for Objective-C objects #ifndef COMMON_APPLE_OBJCPTR_H_ #define COMMON_APPLE_OBJCPTR_H_ #ifndef __OBJC__ # error For Objective-C++ only. #endif #import #import #import #import "common/platform.h" namespace angle { // Smart pointer for holding Objective-C objects. Use adoptObjCPtr for create functions // that return owned reference, e.g. functions that begin with 'new', 'copy', 'create'. template class ObjCPtr { public: using PtrType = std::remove_pointer_t *; constexpr ObjCPtr() = default; constexpr ObjCPtr(std::nullptr_t other) {} ObjCPtr(PtrType other); ObjCPtr(const ObjCPtr &other); template constexpr ObjCPtr(ObjCPtr &&other); ~ObjCPtr(); ObjCPtr &operator=(const ObjCPtr &other); ObjCPtr &operator=(PtrType other); template constexpr ObjCPtr &operator=(ObjCPtr &&other); [[nodiscard]] constexpr PtrType leakObject(); void reset(); constexpr explicit operator bool() const { return get(); } constexpr operator PtrType() const { return get(); } constexpr PtrType get() const { return mObject; } constexpr void swap(ObjCPtr &other); template friend ObjCPtr> adoptObjCPtr(U NS_RELEASES_ARGUMENT); private: struct AdoptTag {}; constexpr ObjCPtr(PtrType other, AdoptTag); PtrType mObject = nil; }; template ObjCPtr(T) -> ObjCPtr>; template ObjCPtr::ObjCPtr(PtrType other) : mObject(other) { #if !__has_feature(objc_arc) [mObject retain]; #endif } template ObjCPtr::ObjCPtr(const ObjCPtr &other) : ObjCPtr(other.mObject) {} template template constexpr ObjCPtr::ObjCPtr(ObjCPtr &&other) : mObject(other.leakObject()) {} template ObjCPtr::~ObjCPtr() { #if !__has_feature(objc_arc) [mObject release]; #endif } template ObjCPtr &ObjCPtr::operator=(const ObjCPtr &other) { ObjCPtr temp = other; swap(temp); return *this; } template template constexpr ObjCPtr &ObjCPtr::operator=(ObjCPtr &&other) { ObjCPtr temp = std::move(other); swap(temp); return *this; } template ObjCPtr &ObjCPtr::operator=(PtrType other) { ObjCPtr temp = other; swap(temp); return *this; } template constexpr ObjCPtr::ObjCPtr(PtrType other, AdoptTag) : mObject(other) {} template constexpr void ObjCPtr::swap(ObjCPtr &other) { // std::swap is constexpr only in c++20. auto object = other.mObject; other.mObject = mObject; mObject = object; } template constexpr typename ObjCPtr::PtrType ObjCPtr::leakObject() { // std::exchange is constexper only in c++20. auto object = mObject; mObject = nullptr; return object; } template void ObjCPtr::reset() { *this = {}; } template constexpr bool operator==(const ObjCPtr &a, const ObjCPtr &b) { return a.get() == b.get(); } template constexpr bool operator==(const ObjCPtr &a, U *b) { return a.get() == b; } template constexpr bool operator==(T *a, const ObjCPtr &b) { return a == b.get(); } template ObjCPtr> adoptObjCPtr(U NS_RELEASES_ARGUMENT other) { using ResultType = ObjCPtr>; return ResultType(other, typename ResultType::AdoptTag{}); } } // namespace angle #endif