1 /*
2 * Copyright 2012 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 #include "include/core/SkRefCnt.h"
9 #include "include/core/SkTypes.h"
10 #include "include/private/SkWeakRefCnt.h"
11 #include "include/private/base/SkDebug.h"
12 #include "tests/Test.h"
13
14 #include <thread>
15 #include <utility>
16
bounce_ref(void * data)17 static void bounce_ref(void* data) {
18 SkRefCnt* ref = static_cast<SkRefCnt*>(data);
19 for (int i = 0; i < 100000; ++i) {
20 ref->ref();
21 ref->unref();
22 }
23 }
24
test_refCnt(skiatest::Reporter * reporter)25 static void test_refCnt(skiatest::Reporter* reporter) {
26 SkRefCnt* ref = new SkRefCnt();
27
28 std::thread thing1(bounce_ref, ref);
29 std::thread thing2(bounce_ref, ref);
30
31 thing1.join();
32 thing2.join();
33
34 REPORTER_ASSERT(reporter, ref->unique());
35 ref->unref();
36 }
37
bounce_weak_ref(void * data)38 static void bounce_weak_ref(void* data) {
39 SkWeakRefCnt* ref = static_cast<SkWeakRefCnt*>(data);
40 for (int i = 0; i < 100000; ++i) {
41 if (ref->try_ref()) {
42 ref->unref();
43 }
44 }
45 }
46
bounce_weak_weak_ref(void * data)47 static void bounce_weak_weak_ref(void* data) {
48 SkWeakRefCnt* ref = static_cast<SkWeakRefCnt*>(data);
49 for (int i = 0; i < 100000; ++i) {
50 ref->weak_ref();
51 ref->weak_unref();
52 }
53 }
54
test_weakRefCnt(skiatest::Reporter * reporter)55 static void test_weakRefCnt(skiatest::Reporter* reporter) {
56 SkWeakRefCnt* ref = new SkWeakRefCnt();
57
58 std::thread thing1(bounce_ref, ref);
59 std::thread thing2(bounce_ref, ref);
60 std::thread thing3(bounce_weak_ref, ref);
61 std::thread thing4(bounce_weak_weak_ref, ref);
62
63 thing1.join();
64 thing2.join();
65 thing3.join();
66 thing4.join();
67
68 REPORTER_ASSERT(reporter, ref->unique());
69 SkDEBUGCODE(REPORTER_ASSERT(reporter, ref->getWeakCnt() == 1));
70 ref->unref();
71 }
72
DEF_TEST(RefCnt,reporter)73 DEF_TEST(RefCnt, reporter) {
74 test_refCnt(reporter);
75 test_weakRefCnt(reporter);
76 }
77
78 ///////////////////////////////////////////////////////////////////////////////////////////////////
79
80 static int gRefCounter;
81 static int gUnrefCounter;
82 static int gNewCounter;
83 static int gDeleteCounter;
84
85 #define check(reporter, ref, unref, make, kill) \
86 REPORTER_ASSERT(reporter, gRefCounter == ref); \
87 REPORTER_ASSERT(reporter, gUnrefCounter == unref); \
88 REPORTER_ASSERT(reporter, gNewCounter == make); \
89 REPORTER_ASSERT(reporter, gDeleteCounter == kill)
90
91 class Effect {
92 public:
Effect()93 Effect() : fRefCnt(1) {
94 gNewCounter += 1;
95 }
~Effect()96 virtual ~Effect() {}
97
98 int fRefCnt;
99
ref()100 void ref() {
101 gRefCounter += 1;
102 fRefCnt += 1;
103 }
unref()104 void unref() {
105 gUnrefCounter += 1;
106
107 SkASSERT(fRefCnt > 0);
108 if (0 == --fRefCnt) {
109 gDeleteCounter += 1;
110 delete this;
111 }
112 }
113
method() const114 int* method() const { return new int; }
115 };
116
Create()117 static sk_sp<Effect> Create() {
118 return sk_make_sp<Effect>();
119 }
120
121 class Paint {
122 public:
123 sk_sp<Effect> fEffect;
124
get() const125 const sk_sp<Effect>& get() const { return fEffect; }
126
set(sk_sp<Effect> value)127 void set(sk_sp<Effect> value) {
128 fEffect = std::move(value);
129 }
130 };
131
132 struct EffectImpl : public Effect {
~EffectImplEffectImpl133 ~EffectImpl() override {}
134
CreateEffectImpl135 static sk_sp<EffectImpl> Create() {
136 return sk_sp<EffectImpl>(new EffectImpl);
137 }
138 int fValue;
139 };
make_effect()140 static sk_sp<Effect> make_effect() {
141 auto foo = EffectImpl::Create();
142 foo->fValue = 42;
143 return foo;
144 }
145
reset_counters()146 static void reset_counters() {
147 gRefCounter = 0;
148 gUnrefCounter = 0;
149 gNewCounter = 0;
150 gDeleteCounter = 0;
151 }
DEF_TEST(sk_sp,reporter)152 DEF_TEST(sk_sp, reporter) {
153 reset_counters();
154
155 Paint paint;
156 REPORTER_ASSERT(reporter, paint.fEffect.get() == nullptr);
157 REPORTER_ASSERT(reporter, !paint.get());
158 check(reporter, 0, 0, 0, 0);
159
160 paint.set(Create());
161 check(reporter, 0, 0, 1, 0);
162 REPORTER_ASSERT(reporter, paint.fEffect.get()->fRefCnt == 1);
163
164 if (paint.get()) {
165 REPORTER_ASSERT(reporter, true);
166 } else {
167 REPORTER_ASSERT(reporter, false);
168 }
169 if (!paint.get()) {
170 REPORTER_ASSERT(reporter, false);
171 } else {
172 REPORTER_ASSERT(reporter, true);
173 }
174
175 paint.set(nullptr);
176 check(reporter, 0, 1, 1, 1);
177
178 if (paint.get()) {
179 REPORTER_ASSERT(reporter, false);
180 } else {
181 REPORTER_ASSERT(reporter, true);
182 }
183 if (!paint.get()) {
184 REPORTER_ASSERT(reporter, true);
185 } else {
186 REPORTER_ASSERT(reporter, false);
187 }
188
189 auto e = Create();
190 REPORTER_ASSERT(reporter, sizeof(e) == sizeof(void*));
191
192 check(reporter, 0, 1, 2, 1);
193 paint.set(e);
194 check(reporter, 1, 1, 2, 1);
195 REPORTER_ASSERT(reporter, paint.fEffect.get()->fRefCnt == 2);
196
197 Paint paint2;
198 paint2.set(paint.get());
199 check(reporter, 2, 1, 2, 1);
200 REPORTER_ASSERT(reporter, paint.fEffect.get()->fRefCnt == 3);
201
202 // Test sk_sp::operator->
203 delete paint.get()->method();
204 check(reporter, 2, 1, 2, 1);
205
206 // Test sk_sp::operator*
207 delete (*paint.get()).method();
208 check(reporter, 2, 1, 2, 1);
209
210 paint.set(nullptr);
211 e = nullptr;
212 paint2.set(nullptr);
213 check(reporter, 2, 4, 2, 2);
214
215 reset_counters();
216 {
217 // Test convertible sk_sp assignment.
218 check(reporter, 0, 0, 0, 0);
219 sk_sp<Effect> foo(nullptr);
220 REPORTER_ASSERT(reporter, !foo);
221 foo = make_effect();
222 REPORTER_ASSERT(reporter, foo);
223 check(reporter, 0, 0, 1, 0);
224 }
225 check(reporter, 0, 1, 1, 1);
226
227 // Test passing convertible rvalue into funtion.
228 reset_counters();
229 paint.set(EffectImpl::Create());
230 check(reporter, 0, 0, 1, 0);
231 paint.set(nullptr);
232 check(reporter, 0, 1, 1, 1);
233
234 reset_counters();
235 auto baz = EffectImpl::Create();
236 check(reporter, 0, 0, 1, 0);
237 paint.set(std::move(baz));
238 check(reporter, 0, 0, 1, 0);
239 REPORTER_ASSERT(reporter, !baz); // NOLINT(bugprone-use-after-move)
240 paint.set(nullptr);
241 check(reporter, 0, 1, 1, 1);
242
243 reset_counters();
244 {
245 // test comparison operator with convertible type.
246 sk_sp<EffectImpl> bar1 = EffectImpl::Create();
247 sk_sp<Effect> bar2(bar1); // convertible copy constructor
248 check(reporter, 1, 0, 1, 0);
249 REPORTER_ASSERT(reporter, bar1);
250 REPORTER_ASSERT(reporter, bar2);
251 REPORTER_ASSERT(reporter, bar1 == bar2);
252 REPORTER_ASSERT(reporter, bar2 == bar1);
253 REPORTER_ASSERT(reporter, !(bar1 != bar2));
254 REPORTER_ASSERT(reporter, !(bar2 != bar1));
255 sk_sp<Effect> bar3(nullptr);
256 bar3 = bar1; // convertible copy assignment
257 check(reporter, 2, 0, 1, 0);
258
259 }
260 check(reporter, 2, 3, 1, 1);
261
262 // test passing convertible copy into funtion.
263 reset_counters();
264 baz = EffectImpl::Create();
265 check(reporter, 0, 0, 1, 0);
266 paint.set(baz);
267 check(reporter, 1, 0, 1, 0);
268 baz = nullptr;
269 check(reporter, 1, 1, 1, 0);
270 paint.set(nullptr);
271 check(reporter, 1, 2, 1, 1);
272
273 {
274 sk_sp<SkRefCnt> empty;
275 sk_sp<SkRefCnt> notEmpty = sk_make_sp<SkRefCnt>();
276 REPORTER_ASSERT(reporter, empty == sk_sp<SkRefCnt>());
277
278 REPORTER_ASSERT(reporter, notEmpty != empty);
279 REPORTER_ASSERT(reporter, empty != notEmpty);
280
281 REPORTER_ASSERT(reporter, nullptr == empty);
282 REPORTER_ASSERT(reporter, empty == nullptr);
283 REPORTER_ASSERT(reporter, empty == empty);
284 }
285
286 {
287 sk_sp<SkRefCnt> a = sk_make_sp<SkRefCnt>();
288 sk_sp<SkRefCnt> b = sk_make_sp<SkRefCnt>();
289 REPORTER_ASSERT(reporter, a != b);
290 REPORTER_ASSERT(reporter, a == a);
291 }
292
293 // http://wg21.cmeerw.net/lwg/issue998
294 {
295 class foo : public SkRefCnt {
296 public:
297 foo() : bar(this) {}
298 void reset() { bar.reset(); }
299 private:
300 sk_sp<foo> bar;
301 };
302 // The following should properly delete the object and not cause undefined behavior.
303 // This is an ugly example, but the same issue can arise in more subtle ways.
304 (new foo)->reset();
305 }
306
307 // https://crrev.com/0d4ef2583a6f19c3e61be04d36eb1a60b133832c
308 {
309 struct StructB;
310 struct StructA : public SkRefCnt {
311 sk_sp<StructB> b;
312 };
313
314 struct StructB : public SkRefCnt {
315 sk_sp<StructA> a;
316 ~StructB() override {} // Some clang versions don't emit this implicitly.
317 };
318
319 // Create a reference cycle.
320 StructA* a = new StructA;
321 a->b.reset(new StructB);
322 a->b->a.reset(a);
323
324 // Break the cycle by calling reset(). This will cause |a| (and hence, |a.b|)
325 // to be deleted before the call to reset() returns. This tests that the
326 // implementation of sk_sp::reset() doesn't access |this| after it
327 // deletes the underlying pointer. This behaviour is consistent with the
328 // definition of unique_ptr::reset in C++11.
329 a->b.reset();
330 }
331 }
332
333 namespace {
334 struct FooAbstract : public SkRefCnt {
335 virtual void f() = 0;
336 };
337 struct FooConcrete : public FooAbstract {
f__anonfaee02530111::FooConcrete338 void f() override {}
339 };
340 } // namespace
make_foo()341 static sk_sp<FooAbstract> make_foo() {
342 // can not cast FooConcrete to FooAbstract.
343 // can cast FooConcrete* to FooAbstract*.
344 return sk_make_sp<FooConcrete>();
345 }
DEF_TEST(sk_make_sp,r)346 DEF_TEST(sk_make_sp, r) {
347 auto x = make_foo();
348 }
349
350 // Test that reset() "adopts" ownership from the caller, even if we are given the same ptr twice
351 //
DEF_TEST(sk_sp_reset,r)352 DEF_TEST(sk_sp_reset, r) {
353 SkRefCnt* rc = new SkRefCnt;
354 REPORTER_ASSERT(r, rc->unique());
355
356 sk_sp<SkRefCnt> sp;
357 sp.reset(rc);
358 // We have transfered our ownership over to sp
359 REPORTER_ASSERT(r, rc->unique());
360
361 rc->ref(); // now "rc" is also an owner
362 REPORTER_ASSERT(r, !rc->unique());
363
364 sp.reset(rc); // this should transfer our ownership over to sp
365 REPORTER_ASSERT(r, rc->unique());
366 }
367
DEF_TEST(sk_sp_ref,r)368 DEF_TEST(sk_sp_ref, r) {
369 SkRefCnt* rc = new SkRefCnt;
370 REPORTER_ASSERT(r, rc->unique());
371
372 {
373 sk_sp<SkRefCnt> sp = sk_ref_sp(rc);
374 REPORTER_ASSERT(r, !rc->unique());
375 }
376
377 REPORTER_ASSERT(r, rc->unique());
378 rc->unref();
379 }
380