Flutter Engine
The Flutter Engine
SkCFObject.h
Go to the documentation of this file.
1/*
2 * Copyright 2019 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#ifndef SkCFObject_DEFINED
9#define SkCFObject_DEFINED
10
11#ifdef __APPLE__
12
14
15#include <cstddef> // std::nullptr_t
16
17#import <CoreFoundation/CoreFoundation.h>
18
19/**
20 * Wrapper class for managing lifetime of CoreFoundation objects. It will call
21 * CFRetain and CFRelease appropriately on creation, assignment, and deletion.
22 * Based on sk_sp<>.
23 */
24template <typename T> static inline T SkCFSafeRetain(T obj) {
25 if (obj) {
26 CFRetain(obj);
27 }
28 return obj;
29}
30
31template <typename T> static inline void SkCFSafeRelease(T obj) {
32 if (obj) {
33 CFRelease(obj);
34 }
35}
36
37template <typename T> class sk_cfp {
38public:
39 using element_type = T;
40
41 constexpr sk_cfp() {}
42 constexpr sk_cfp(std::nullptr_t) {}
43
44 /**
45 * Shares the underlying object by calling CFRetain(), so that both the argument and the newly
46 * created sk_cfp both have a reference to it.
47 */
48 sk_cfp(const sk_cfp<T>& that) : fObject(SkCFSafeRetain(that.get())) {}
49
50 /**
51 * Move the underlying object from the argument to the newly created sk_cfp. Afterwards only
52 * the new sk_cfp will have a reference to the object, and the argument will point to null.
53 * No call to CFRetain() or CFRelease() will be made.
54 */
55 sk_cfp(sk_cfp<T>&& that) : fObject(that.release()) {}
56
57 /**
58 * Adopt the bare object into the newly created sk_cfp.
59 * No call to CFRetain() or CFRelease() will be made.
60 */
61 explicit sk_cfp(T obj) {
62 fObject = obj;
63 }
64
65 /**
66 * Calls CFRelease() on the underlying object pointer.
67 */
68 ~sk_cfp() {
69 SkCFSafeRelease(fObject);
70 SkDEBUGCODE(fObject = nil);
71 }
72
73 sk_cfp<T>& operator=(std::nullptr_t) { this->reset(); return *this; }
74
75 /**
76 * Shares the underlying object referenced by the argument by calling CFRetain() on it. If this
77 * sk_cfp previously had a reference to an object (i.e. not null) it will call CFRelease()
78 * on that object.
79 */
80 sk_cfp<T>& operator=(const sk_cfp<T>& that) {
81 if (this != &that) {
82 this->reset(SkCFSafeRetain(that.get()));
83 }
84 return *this;
85 }
86
87 /**
88 * Move the underlying object from the argument to the sk_cfp. If the sk_cfp
89 * previously held a reference to another object, CFRelease() will be called on that object.
90 * No call to CFRetain() will be made.
91 */
92 sk_cfp<T>& operator=(sk_cfp<T>&& that) {
93 this->reset(that.release());
94 return *this;
95 }
96
97 explicit operator bool() const { return this->get() != nil; }
98
99 T get() const { return fObject; }
100 T operator*() const {
101 SkASSERT(fObject);
102 return fObject;
103 }
104
105 /**
106 * Adopt the new object, and call CFRelease() on any previously held object (if not null).
107 * No call to CFRetain() will be made.
108 */
109 void reset(T object = nil) {
110 // Need to unref after assigning, see
111 // http://wg21.cmeerw.net/lwg/issue998
112 // http://wg21.cmeerw.net/lwg/issue2262
113 T oldObject = fObject;
114 fObject = object;
115 SkCFSafeRelease(oldObject);
116 }
117
118 /**
119 * Shares the new object by calling CFRetain() on it. If this sk_cfp previously had a
120 * reference to an object (i.e. not null) it will call CFRelease() on that object.
121 */
122 void retain(T object) {
123 if (fObject != object) {
124 this->reset(SkCFSafeRetain(object));
125 }
126 }
127
128 /**
129 * Return the original object, and set the internal object to nullptr.
130 * The caller must assume ownership of the object, and manage its reference count directly.
131 * No call to CFRelease() will be made.
132 */
133 [[nodiscard]] T release() {
134 T obj = fObject;
135 fObject = nil;
136 return obj;
137 }
138
139private:
140 T fObject = nil;
141};
142
143template <typename T> inline bool operator==(const sk_cfp<T>& a,
144 const sk_cfp<T>& b) {
145 return a.get() == b.get();
146}
147template <typename T> inline bool operator==(const sk_cfp<T>& a,
148 std::nullptr_t) {
149 return !a;
150}
151template <typename T> inline bool operator==(std::nullptr_t,
152 const sk_cfp<T>& b) {
153 return !b;
154}
155
156template <typename T> inline bool operator!=(const sk_cfp<T>& a,
157 const sk_cfp<T>& b) {
158 return a.get() != b.get();
159}
160template <typename T> inline bool operator!=(const sk_cfp<T>& a,
161 std::nullptr_t) {
162 return static_cast<bool>(a);
163}
164template <typename T> inline bool operator!=(std::nullptr_t,
165 const sk_cfp<T>& b) {
166 return static_cast<bool>(b);
167}
168
169/*
170 * Returns a sk_cfp wrapping the provided object AND calls retain on it (if not null).
171 *
172 * This is different than the semantics of the constructor for sk_cfp, which just wraps the
173 * object, effectively "adopting" it.
174 */
175template <typename T> sk_cfp<T> sk_ret_cfp(T obj) {
176 return sk_cfp<T>(SkCFSafeRetain(obj));
177}
178
179#endif // __APPLE__
180#endif // SkCFObject_DEFINED
m reset()
#define SkASSERT(cond)
Definition: SkAssert.h:116
SkDEBUGCODE(SK_SPI) SkThreadID SkGetThreadID()
static bool b
struct MyStruct a[10]
bool operator==(C p1, const scoped_nsprotocol< C > &p2)
bool operator!=(C p1, const scoped_nsprotocol< C > &p2)
constexpr Color operator*(T value, const Color &c)
Definition: color.h:911
const myers::Point & get(const myers::Segment &)
#define T
Definition: precompiler.cc:65