• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2025 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 // ObjCPtr.h:
7 //      Implements smart pointer for Objective-C objects
8 
9 #ifndef COMMON_APPLE_OBJCPTR_H_
10 #define COMMON_APPLE_OBJCPTR_H_
11 
12 #ifndef __OBJC__
13 #    error For Objective-C++ only.
14 #endif
15 
16 #import <Foundation/Foundation.h>
17 #import <type_traits>
18 #import <utility>
19 #import "common/platform.h"
20 
21 namespace angle
22 {
23 
24 // Smart pointer for holding Objective-C objects. Use adoptObjCPtr for create functions
25 // that return owned reference, e.g. functions that begin with 'new', 'copy', 'create'.
26 template <typename T>
27 class ObjCPtr
28 {
29   public:
30     using PtrType = std::remove_pointer_t<T> *;
31 
32     constexpr ObjCPtr() = default;
ObjCPtr(std::nullptr_t other)33     constexpr ObjCPtr(std::nullptr_t other) {}
34     ObjCPtr(PtrType other);
35     ObjCPtr(const ObjCPtr &other);
36     template <typename U>
37     constexpr ObjCPtr(ObjCPtr<U> &&other);
38     ~ObjCPtr();
39     ObjCPtr &operator=(const ObjCPtr &other);
40     ObjCPtr &operator=(PtrType other);
41     template <typename U>
42     constexpr ObjCPtr &operator=(ObjCPtr<U> &&other);
43 
44     [[nodiscard]] constexpr PtrType leakObject();
45     void reset();
46 
47     constexpr explicit operator bool() const { return get(); }
PtrType()48     constexpr operator PtrType() const { return get(); }
get()49     constexpr PtrType get() const { return mObject; }
50     constexpr void swap(ObjCPtr<T> &other);
51 
52     template <typename U>
53     friend ObjCPtr<std::remove_pointer_t<U>> adoptObjCPtr(U NS_RELEASES_ARGUMENT);
54 
55   private:
56     struct AdoptTag
57     {};
58     constexpr ObjCPtr(PtrType other, AdoptTag);
59 
60     PtrType mObject = nil;
61 };
62 
63 template <typename T>
64 ObjCPtr(T) -> ObjCPtr<std::remove_pointer_t<T>>;
65 
66 template <typename T>
ObjCPtr(PtrType other)67 ObjCPtr<T>::ObjCPtr(PtrType other) : mObject(other)
68 {
69 #if !__has_feature(objc_arc)
70     [mObject retain];
71 #endif
72 }
73 
74 template <typename T>
ObjCPtr(const ObjCPtr & other)75 ObjCPtr<T>::ObjCPtr(const ObjCPtr &other) : ObjCPtr(other.mObject)
76 {}
77 
78 template <typename T>
79 template <typename U>
ObjCPtr(ObjCPtr<U> && other)80 constexpr ObjCPtr<T>::ObjCPtr(ObjCPtr<U> &&other) : mObject(other.leakObject())
81 {}
82 
83 template <typename T>
~ObjCPtr()84 ObjCPtr<T>::~ObjCPtr()
85 {
86 #if !__has_feature(objc_arc)
87     [mObject release];
88 #endif
89 }
90 
91 template <typename T>
92 ObjCPtr<T> &ObjCPtr<T>::operator=(const ObjCPtr &other)
93 {
94     ObjCPtr temp = other;
95     swap(temp);
96     return *this;
97 }
98 
99 template <typename T>
100 template <typename U>
101 constexpr ObjCPtr<T> &ObjCPtr<T>::operator=(ObjCPtr<U> &&other)
102 {
103     ObjCPtr temp = std::move(other);
104     swap(temp);
105     return *this;
106 }
107 
108 template <typename T>
109 ObjCPtr<T> &ObjCPtr<T>::operator=(PtrType other)
110 {
111     ObjCPtr temp = other;
112     swap(temp);
113     return *this;
114 }
115 
116 template <typename T>
ObjCPtr(PtrType other,AdoptTag)117 constexpr ObjCPtr<T>::ObjCPtr(PtrType other, AdoptTag) : mObject(other)
118 {}
119 
120 template <typename T>
swap(ObjCPtr<T> & other)121 constexpr void ObjCPtr<T>::swap(ObjCPtr<T> &other)
122 {
123     // std::swap is constexpr only in c++20.
124     auto object   = other.mObject;
125     other.mObject = mObject;
126     mObject       = object;
127 }
128 
129 template <typename T>
leakObject()130 constexpr typename ObjCPtr<T>::PtrType ObjCPtr<T>::leakObject()
131 {
132     // std::exchange is constexper only in c++20.
133     auto object = mObject;
134     mObject     = nullptr;
135     return object;
136 }
137 
138 template <typename T>
reset()139 void ObjCPtr<T>::reset()
140 {
141     *this = {};
142 }
143 
144 template <typename T, typename U>
145 constexpr bool operator==(const ObjCPtr<T> &a, const ObjCPtr<U> &b)
146 {
147     return a.get() == b.get();
148 }
149 
150 template <typename T, typename U>
151 constexpr bool operator==(const ObjCPtr<T> &a, U *b)
152 {
153     return a.get() == b;
154 }
155 
156 template <typename T, typename U>
157 constexpr bool operator==(T *a, const ObjCPtr<U> &b)
158 {
159     return a == b.get();
160 }
161 
162 template <typename U>
adoptObjCPtr(U NS_RELEASES_ARGUMENT other)163 ObjCPtr<std::remove_pointer_t<U>> adoptObjCPtr(U NS_RELEASES_ARGUMENT other)
164 {
165     using ResultType = ObjCPtr<std::remove_pointer_t<U>>;
166     return ResultType(other, typename ResultType::AdoptTag{});
167 }
168 
169 }  // namespace angle
170 
171 #endif
172