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