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#include <thread>
13
14static void bounce_ref(void* data) {
15    SkRefCnt* ref = static_cast<SkRefCnt*>(data);
16    for (int i = 0; i < 100000; ++i) {
17        ref->ref();
18        ref->unref();
19    }
20}
21
22static void test_refCnt(skiatest::Reporter* reporter) {
23    SkRefCnt* ref = new SkRefCnt();
24
25    std::thread thing1(bounce_ref, ref);
26    std::thread thing2(bounce_ref, ref);
27
28    thing1.join();
29    thing2.join();
30
31    REPORTER_ASSERT(reporter, ref->unique());
32    ref->unref();
33}
34
35static void bounce_weak_ref(void* data) {
36    SkWeakRefCnt* ref = static_cast<SkWeakRefCnt*>(data);
37    for (int i = 0; i < 100000; ++i) {
38        if (ref->try_ref()) {
39            ref->unref();
40        }
41    }
42}
43
44static void bounce_weak_weak_ref(void* data) {
45    SkWeakRefCnt* ref = static_cast<SkWeakRefCnt*>(data);
46    for (int i = 0; i < 100000; ++i) {
47        ref->weak_ref();
48        ref->weak_unref();
49    }
50}
51
52static void test_weakRefCnt(skiatest::Reporter* reporter) {
53    SkWeakRefCnt* ref = new SkWeakRefCnt();
54
55    std::thread thing1(bounce_ref, ref);
56    std::thread thing2(bounce_ref, ref);
57    std::thread thing3(bounce_weak_ref, ref);
58    std::thread thing4(bounce_weak_weak_ref, ref);
59
60    thing1.join();
61    thing2.join();
62    thing3.join();
63    thing4.join();
64
65    REPORTER_ASSERT(reporter, ref->unique());
66    SkDEBUGCODE(REPORTER_ASSERT(reporter, ref->getWeakCnt() == 1));
67    ref->unref();
68}
69
70DEF_TEST(RefCnt, reporter) {
71    test_refCnt(reporter);
72    test_weakRefCnt(reporter);
73}
74
75///////////////////////////////////////////////////////////////////////////////////////////////////
76
77static int gRefCounter;
78static int gUnrefCounter;
79static int gNewCounter;
80static int gDeleteCounter;
81
82#define check(reporter, ref, unref, make, kill)             \
83    REPORTER_ASSERT(reporter, gRefCounter == ref);          \
84    REPORTER_ASSERT(reporter, gUnrefCounter == unref);      \
85    REPORTER_ASSERT(reporter, gNewCounter == make);         \
86    REPORTER_ASSERT(reporter, gDeleteCounter == kill);
87
88
89class Effect {
90public:
91    Effect() : fRefCnt(1) {
92        gNewCounter += 1;
93    }
94    virtual ~Effect() {}
95
96    int fRefCnt;
97
98    void ref() {
99        gRefCounter += 1;
100        fRefCnt += 1;
101    }
102    void unref() {
103        gUnrefCounter += 1;
104
105        SkASSERT(fRefCnt > 0);
106        if (0 == --fRefCnt) {
107            gDeleteCounter += 1;
108            delete this;
109        }
110    }
111
112    int* method() const { return new int; }
113};
114
115static sk_sp<Effect> Create() {
116    return sk_make_sp<Effect>();
117}
118
119class Paint {
120public:
121    sk_sp<Effect> fEffect;
122
123    const sk_sp<Effect>& get() const { return fEffect; }
124
125    void set(sk_sp<Effect> value) {
126        fEffect = std::move(value);
127    }
128};
129
130struct EffectImpl : public Effect {
131    ~EffectImpl() override {}
132
133    static sk_sp<EffectImpl> Create() {
134        return sk_sp<EffectImpl>(new EffectImpl);
135    }
136    int fValue;
137};
138static sk_sp<Effect> make_effect() {
139    auto foo = EffectImpl::Create();
140    foo->fValue = 42;
141    return std::move(foo);
142}
143
144static void reset_counters() {
145    gRefCounter = 0;
146    gUnrefCounter = 0;
147    gNewCounter = 0;
148    gDeleteCounter = 0;
149}
150DEF_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);
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
346namespace {
347struct FooAbstract : public SkRefCnt {
348    virtual void f() = 0;
349};
350struct FooConcrete : public FooAbstract {
351    void f() override {}
352};
353}
354static 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}
359DEF_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//
365DEF_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
381DEF_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