1554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com/*
2554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com * Copyright 2012 Google Inc.
3554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com *
4554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com * Use of this source code is governed by a BSD-style license that can be
5554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com * found in the LICENSE file.
6554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com */
7554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com
8554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com#include "SkRefCnt.h"
9e4fafb146e85cdfcf9d5418597b6818aa0754adatfarina@chromium.org#include "SkTypes.h"
10a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com#include "SkWeakRefCnt.h"
118f6884aab8aecd7657cf3f9cdbc682f0deca29c5tfarina@chromium.org#include "Test.h"
1203141d25cf75c4ce6cdb94f90e9538ee3c878699Mike Klein#include <thread>
13554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com
14554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.comstatic void bounce_ref(void* data) {
15554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com    SkRefCnt* ref = static_cast<SkRefCnt*>(data);
16554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com    for (int i = 0; i < 100000; ++i) {
17554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com        ref->ref();
18554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com        ref->unref();
19554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com    }
20554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com}
21554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com
22554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.comstatic void test_refCnt(skiatest::Reporter* reporter) {
23554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com    SkRefCnt* ref = new SkRefCnt();
24554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com
2503141d25cf75c4ce6cdb94f90e9538ee3c878699Mike Klein    std::thread thing1(bounce_ref, ref);
2603141d25cf75c4ce6cdb94f90e9538ee3c878699Mike Klein    std::thread thing2(bounce_ref, ref);
27554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com
28554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com    thing1.join();
29554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com    thing2.join();
30554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com
31bbb61d7268b26d240afde2c924cb7d1370aa4071mtklein    REPORTER_ASSERT(reporter, ref->unique());
32554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com    ref->unref();
33554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com}
34554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com
35a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.comstatic void bounce_weak_ref(void* data) {
36a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com    SkWeakRefCnt* ref = static_cast<SkWeakRefCnt*>(data);
37a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com    for (int i = 0; i < 100000; ++i) {
38a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com        if (ref->try_ref()) {
39a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com            ref->unref();
40a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com        }
41a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com    }
42a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com}
43a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com
44a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.comstatic void bounce_weak_weak_ref(void* data) {
45a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com    SkWeakRefCnt* ref = static_cast<SkWeakRefCnt*>(data);
46a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com    for (int i = 0; i < 100000; ++i) {
47a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com        ref->weak_ref();
48a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com        ref->weak_unref();
49a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com    }
50a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com}
51a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com
52a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.comstatic void test_weakRefCnt(skiatest::Reporter* reporter) {
53a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com    SkWeakRefCnt* ref = new SkWeakRefCnt();
54a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com
5503141d25cf75c4ce6cdb94f90e9538ee3c878699Mike Klein    std::thread thing1(bounce_ref, ref);
5603141d25cf75c4ce6cdb94f90e9538ee3c878699Mike Klein    std::thread thing2(bounce_ref, ref);
5703141d25cf75c4ce6cdb94f90e9538ee3c878699Mike Klein    std::thread thing3(bounce_weak_ref, ref);
5803141d25cf75c4ce6cdb94f90e9538ee3c878699Mike Klein    std::thread thing4(bounce_weak_weak_ref, ref);
59a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com
60a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com    thing1.join();
61a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com    thing2.join();
62a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com    thing3.join();
63a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com    thing4.join();
64a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com
65bbb61d7268b26d240afde2c924cb7d1370aa4071mtklein    REPORTER_ASSERT(reporter, ref->unique());
662c4bd0798e929acb9663668985eabe74d7378c46bungeman    SkDEBUGCODE(REPORTER_ASSERT(reporter, ref->getWeakCnt() == 1));
67a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com    ref->unref();
68a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com}
69a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com
70e4fafb146e85cdfcf9d5418597b6818aa0754adatfarina@chromium.orgDEF_TEST(RefCnt, reporter) {
71a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com    test_refCnt(reporter);
72a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com    test_weakRefCnt(reporter);
73a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com}
74bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed
75bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed///////////////////////////////////////////////////////////////////////////////////////////////////
76bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed
77bb7b043b2db64197d2f6a1edaf3562a50c77afb1reedstatic int gRefCounter;
78bb7b043b2db64197d2f6a1edaf3562a50c77afb1reedstatic int gUnrefCounter;
79bb7b043b2db64197d2f6a1edaf3562a50c77afb1reedstatic int gNewCounter;
80bb7b043b2db64197d2f6a1edaf3562a50c77afb1reedstatic int gDeleteCounter;
81bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed
82bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed#define check(reporter, ref, unref, make, kill)             \
83bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    REPORTER_ASSERT(reporter, gRefCounter == ref);          \
84bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    REPORTER_ASSERT(reporter, gUnrefCounter == unref);      \
85bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    REPORTER_ASSERT(reporter, gNewCounter == make);         \
86bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    REPORTER_ASSERT(reporter, gDeleteCounter == kill);
87bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed
88bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed
89bb7b043b2db64197d2f6a1edaf3562a50c77afb1reedclass Effect {
90bb7b043b2db64197d2f6a1edaf3562a50c77afb1reedpublic:
91bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    Effect() : fRefCnt(1) {
92bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed        gNewCounter += 1;
93bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    }
9471aca549914c868d50cd51ddff3fb7a5bfe250cdmtklein    virtual ~Effect() {}
95bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed
96bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    int fRefCnt;
97bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed
98bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    void ref() {
99bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed        gRefCounter += 1;
100bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed        fRefCnt += 1;
101bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    }
102bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    void unref() {
103bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed        gUnrefCounter += 1;
104bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed
105bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed        SkASSERT(fRefCnt > 0);
106bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed        if (0 == --fRefCnt) {
107bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed            gDeleteCounter += 1;
108bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed            delete this;
109bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed        }
110bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    }
111bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed
112bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    int* method() const { return new int; }
113bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed};
114bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed
115bb7b043b2db64197d2f6a1edaf3562a50c77afb1reedstatic sk_sp<Effect> Create() {
116217c0b3f137d824413e806759bc25378abbe8c18halcanary    return sk_make_sp<Effect>();
117bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed}
118bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed
119bb7b043b2db64197d2f6a1edaf3562a50c77afb1reedclass Paint {
120bb7b043b2db64197d2f6a1edaf3562a50c77afb1reedpublic:
121bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    sk_sp<Effect> fEffect;
122bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed
123bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    const sk_sp<Effect>& get() const { return fEffect; }
124bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed
125bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    void set(sk_sp<Effect> value) {
126bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed        fEffect = std::move(value);
127bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    }
128bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed};
129bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed
130cb6cb3841adec77d178c6d6ed006102077fd3c48halcanarystruct EffectImpl : public Effect {
13171aca549914c868d50cd51ddff3fb7a5bfe250cdmtklein    ~EffectImpl() override {}
13271aca549914c868d50cd51ddff3fb7a5bfe250cdmtklein
133cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary    static sk_sp<EffectImpl> Create() {
134cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary        return sk_sp<EffectImpl>(new EffectImpl);
135cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary    }
136cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary    int fValue;
137cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary};
138cb6cb3841adec77d178c6d6ed006102077fd3c48halcanarystatic sk_sp<Effect> make_effect() {
139cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary    auto foo = EffectImpl::Create();
140cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary    foo->fValue = 42;
141cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary    return std::move(foo);
142cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary}
143cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary
144cb6cb3841adec77d178c6d6ed006102077fd3c48halcanarystatic void reset_counters() {
145bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    gRefCounter = 0;
146bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    gUnrefCounter = 0;
147bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    gNewCounter = 0;
148bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    gDeleteCounter = 0;
149cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary}
150cb6cb3841adec77d178c6d6ed006102077fd3c48halcanaryDEF_TEST(sk_sp, reporter) {
151cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary    reset_counters();
152bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed
153bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    Paint paint;
154bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    REPORTER_ASSERT(reporter, paint.fEffect.get() == nullptr);
155bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    REPORTER_ASSERT(reporter, !paint.get());
156bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    check(reporter, 0, 0, 0, 0);
157bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed
158bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    paint.set(Create());
159bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    check(reporter, 0, 0, 1, 0);
160bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    REPORTER_ASSERT(reporter, paint.fEffect.get()->fRefCnt == 1);
161bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed
162beab9e7ba06ea8bd01fcbfd44f2ca2ed69c8a1d9bungeman    if (paint.get()) {
163beab9e7ba06ea8bd01fcbfd44f2ca2ed69c8a1d9bungeman        REPORTER_ASSERT(reporter, true);
164beab9e7ba06ea8bd01fcbfd44f2ca2ed69c8a1d9bungeman    } else {
165beab9e7ba06ea8bd01fcbfd44f2ca2ed69c8a1d9bungeman        REPORTER_ASSERT(reporter, false);
166beab9e7ba06ea8bd01fcbfd44f2ca2ed69c8a1d9bungeman    }
167beab9e7ba06ea8bd01fcbfd44f2ca2ed69c8a1d9bungeman    if (!paint.get()) {
168beab9e7ba06ea8bd01fcbfd44f2ca2ed69c8a1d9bungeman        REPORTER_ASSERT(reporter, false);
169beab9e7ba06ea8bd01fcbfd44f2ca2ed69c8a1d9bungeman    } else {
170beab9e7ba06ea8bd01fcbfd44f2ca2ed69c8a1d9bungeman        REPORTER_ASSERT(reporter, true);
171beab9e7ba06ea8bd01fcbfd44f2ca2ed69c8a1d9bungeman    }
172beab9e7ba06ea8bd01fcbfd44f2ca2ed69c8a1d9bungeman
173bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    paint.set(nullptr);
174bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    check(reporter, 0, 1, 1, 1);
175bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed
176beab9e7ba06ea8bd01fcbfd44f2ca2ed69c8a1d9bungeman    if (paint.get()) {
177beab9e7ba06ea8bd01fcbfd44f2ca2ed69c8a1d9bungeman        REPORTER_ASSERT(reporter, false);
178beab9e7ba06ea8bd01fcbfd44f2ca2ed69c8a1d9bungeman    } else {
179beab9e7ba06ea8bd01fcbfd44f2ca2ed69c8a1d9bungeman        REPORTER_ASSERT(reporter, true);
180beab9e7ba06ea8bd01fcbfd44f2ca2ed69c8a1d9bungeman    }
181beab9e7ba06ea8bd01fcbfd44f2ca2ed69c8a1d9bungeman    if (!paint.get()) {
182beab9e7ba06ea8bd01fcbfd44f2ca2ed69c8a1d9bungeman        REPORTER_ASSERT(reporter, true);
183beab9e7ba06ea8bd01fcbfd44f2ca2ed69c8a1d9bungeman    } else {
184beab9e7ba06ea8bd01fcbfd44f2ca2ed69c8a1d9bungeman        REPORTER_ASSERT(reporter, false);
185beab9e7ba06ea8bd01fcbfd44f2ca2ed69c8a1d9bungeman    }
186beab9e7ba06ea8bd01fcbfd44f2ca2ed69c8a1d9bungeman
187bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    auto e = Create();
188bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    REPORTER_ASSERT(reporter, sizeof(e) == sizeof(void*));
189bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed
190bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    check(reporter, 0, 1, 2, 1);
191bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    paint.set(e);
192bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    check(reporter, 1, 1, 2, 1);
193bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    REPORTER_ASSERT(reporter, paint.fEffect.get()->fRefCnt == 2);
194bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed
195bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    Paint paint2;
196bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    paint2.set(paint.get());
197bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    check(reporter, 2, 1, 2, 1);
198bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    REPORTER_ASSERT(reporter, paint.fEffect.get()->fRefCnt == 3);
199bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed
200beab9e7ba06ea8bd01fcbfd44f2ca2ed69c8a1d9bungeman    // Test sk_sp::operator->
201bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    delete paint.get()->method();
202bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    check(reporter, 2, 1, 2, 1);
203cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary
204beab9e7ba06ea8bd01fcbfd44f2ca2ed69c8a1d9bungeman    // Test sk_sp::operator*
205beab9e7ba06ea8bd01fcbfd44f2ca2ed69c8a1d9bungeman    delete (*paint.get()).method();
206beab9e7ba06ea8bd01fcbfd44f2ca2ed69c8a1d9bungeman    check(reporter, 2, 1, 2, 1);
207beab9e7ba06ea8bd01fcbfd44f2ca2ed69c8a1d9bungeman
208cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary    paint.set(nullptr);
209cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary    e = nullptr;
210cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary    paint2.set(nullptr);
211cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary    check(reporter, 2, 4, 2, 2);
212cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary
213cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary    reset_counters();
214cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary    {
215cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary        // Test convertible sk_sp assignment.
216cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary        check(reporter, 0, 0, 0, 0);
217cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary        sk_sp<Effect> foo(nullptr);
218cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary        REPORTER_ASSERT(reporter, !foo);
219cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary        foo = make_effect();
220cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary        REPORTER_ASSERT(reporter, foo);
221cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary        check(reporter, 0, 0, 1, 0);
222cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary    }
223cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary    check(reporter, 0, 1, 1, 1);
224cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary
225cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary    // Test passing convertible rvalue into funtion.
226cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary    reset_counters();
227cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary    paint.set(EffectImpl::Create());
228cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary    check(reporter, 0, 0, 1, 0);
229cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary    paint.set(nullptr);
230cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary    check(reporter, 0, 1, 1, 1);
231cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary
232cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary    reset_counters();
233cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary    auto baz = EffectImpl::Create();
234cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary    check(reporter, 0, 0, 1, 0);
235cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary    paint.set(std::move(baz));
236cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary    check(reporter, 0, 0, 1, 0);
237cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary    REPORTER_ASSERT(reporter, !baz);
238cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary    paint.set(nullptr);
239cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary    check(reporter, 0, 1, 1, 1);
240cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary
241cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary    reset_counters();
242cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary    {
243cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary        // test comparison operator with convertible type.
244cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary        sk_sp<EffectImpl> bar1 = EffectImpl::Create();
245cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary        sk_sp<Effect> bar2(bar1);  // convertible copy constructor
246cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary        check(reporter, 1, 0, 1, 0);
247cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary        REPORTER_ASSERT(reporter, bar1);
248cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary        REPORTER_ASSERT(reporter, bar2);
249cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary        REPORTER_ASSERT(reporter, bar1 == bar2);
250cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary        REPORTER_ASSERT(reporter, bar2 == bar1);
251cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary        REPORTER_ASSERT(reporter, !(bar1 != bar2));
252cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary        REPORTER_ASSERT(reporter, !(bar2 != bar1));
253cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary        sk_sp<Effect> bar3(nullptr);
254cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary        bar3 = bar1;  // convertible copy assignment
255cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary        check(reporter, 2, 0, 1, 0);
256cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary
257cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary    }
258cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary    check(reporter, 2, 3, 1, 1);
259cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary
260cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary    // test passing convertible copy into funtion.
261cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary    reset_counters();
262cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary    baz = EffectImpl::Create();
263cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary    check(reporter, 0, 0, 1, 0);
264cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary    paint.set(baz);
265cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary    check(reporter, 1, 0, 1, 0);
266cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary    baz = nullptr;
267cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary    check(reporter, 1, 1, 1, 0);
268cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary    paint.set(nullptr);
269cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary    check(reporter, 1, 2, 1, 1);
270c901c11549acd19e7fc225276f78374ac1600496bungeman
271c901c11549acd19e7fc225276f78374ac1600496bungeman    {
272c901c11549acd19e7fc225276f78374ac1600496bungeman        sk_sp<SkRefCnt> empty;
273c901c11549acd19e7fc225276f78374ac1600496bungeman        sk_sp<SkRefCnt> notEmpty = sk_make_sp<SkRefCnt>();
274c901c11549acd19e7fc225276f78374ac1600496bungeman        REPORTER_ASSERT(reporter, empty == sk_sp<SkRefCnt>());
275c901c11549acd19e7fc225276f78374ac1600496bungeman
276c901c11549acd19e7fc225276f78374ac1600496bungeman        REPORTER_ASSERT(reporter, notEmpty != empty);
277c901c11549acd19e7fc225276f78374ac1600496bungeman        REPORTER_ASSERT(reporter, empty != notEmpty);
278c901c11549acd19e7fc225276f78374ac1600496bungeman
279c901c11549acd19e7fc225276f78374ac1600496bungeman        REPORTER_ASSERT(reporter, nullptr == empty);
280c901c11549acd19e7fc225276f78374ac1600496bungeman        REPORTER_ASSERT(reporter, empty == nullptr);
281c901c11549acd19e7fc225276f78374ac1600496bungeman        REPORTER_ASSERT(reporter, empty == empty);
282c901c11549acd19e7fc225276f78374ac1600496bungeman
283c901c11549acd19e7fc225276f78374ac1600496bungeman        REPORTER_ASSERT(reporter, nullptr <= empty);
284c901c11549acd19e7fc225276f78374ac1600496bungeman        REPORTER_ASSERT(reporter, empty <= nullptr);
285c901c11549acd19e7fc225276f78374ac1600496bungeman        REPORTER_ASSERT(reporter, empty <= empty);
286c901c11549acd19e7fc225276f78374ac1600496bungeman
287c901c11549acd19e7fc225276f78374ac1600496bungeman        REPORTER_ASSERT(reporter, nullptr >= empty);
288c901c11549acd19e7fc225276f78374ac1600496bungeman        REPORTER_ASSERT(reporter, empty >= nullptr);
289c901c11549acd19e7fc225276f78374ac1600496bungeman        REPORTER_ASSERT(reporter, empty >= empty);
290c901c11549acd19e7fc225276f78374ac1600496bungeman    }
291c901c11549acd19e7fc225276f78374ac1600496bungeman
292c901c11549acd19e7fc225276f78374ac1600496bungeman    {
293c901c11549acd19e7fc225276f78374ac1600496bungeman        sk_sp<SkRefCnt> a = sk_make_sp<SkRefCnt>();
294c901c11549acd19e7fc225276f78374ac1600496bungeman        sk_sp<SkRefCnt> b = sk_make_sp<SkRefCnt>();
295c901c11549acd19e7fc225276f78374ac1600496bungeman        REPORTER_ASSERT(reporter, a != b);
296c901c11549acd19e7fc225276f78374ac1600496bungeman        REPORTER_ASSERT(reporter, (a < b) != (b < a));
297c901c11549acd19e7fc225276f78374ac1600496bungeman        REPORTER_ASSERT(reporter, (b > a) != (a > b));
298c901c11549acd19e7fc225276f78374ac1600496bungeman        REPORTER_ASSERT(reporter, (a <= b) != (b <= a));
299c901c11549acd19e7fc225276f78374ac1600496bungeman        REPORTER_ASSERT(reporter, (b >= a) != (a >= b));
300c901c11549acd19e7fc225276f78374ac1600496bungeman
301c901c11549acd19e7fc225276f78374ac1600496bungeman        REPORTER_ASSERT(reporter, a == a);
302c901c11549acd19e7fc225276f78374ac1600496bungeman        REPORTER_ASSERT(reporter, a <= a);
303c901c11549acd19e7fc225276f78374ac1600496bungeman        REPORTER_ASSERT(reporter, a >= a);
304c901c11549acd19e7fc225276f78374ac1600496bungeman    }
305c901c11549acd19e7fc225276f78374ac1600496bungeman
306c901c11549acd19e7fc225276f78374ac1600496bungeman    // http://wg21.cmeerw.net/lwg/issue998
307c901c11549acd19e7fc225276f78374ac1600496bungeman    {
308c901c11549acd19e7fc225276f78374ac1600496bungeman        class foo : public SkRefCnt {
309c901c11549acd19e7fc225276f78374ac1600496bungeman        public:
310c901c11549acd19e7fc225276f78374ac1600496bungeman            foo() : bar(this) {}
311c901c11549acd19e7fc225276f78374ac1600496bungeman            void reset() { bar.reset(); }
312c901c11549acd19e7fc225276f78374ac1600496bungeman        private:
313c901c11549acd19e7fc225276f78374ac1600496bungeman            sk_sp<foo> bar;
314c901c11549acd19e7fc225276f78374ac1600496bungeman        };
315c901c11549acd19e7fc225276f78374ac1600496bungeman        // The following should properly delete the object and not cause undefined behavior.
316c901c11549acd19e7fc225276f78374ac1600496bungeman        // This is an ugly example, but the same issue can arise in more subtle ways.
317c901c11549acd19e7fc225276f78374ac1600496bungeman        (new foo)->reset();
318c901c11549acd19e7fc225276f78374ac1600496bungeman    }
319c901c11549acd19e7fc225276f78374ac1600496bungeman
320c901c11549acd19e7fc225276f78374ac1600496bungeman    // https://crrev.com/0d4ef2583a6f19c3e61be04d36eb1a60b133832c
321c901c11549acd19e7fc225276f78374ac1600496bungeman    {
322c901c11549acd19e7fc225276f78374ac1600496bungeman        struct StructB;
323c901c11549acd19e7fc225276f78374ac1600496bungeman        struct StructA : public SkRefCnt {
324c901c11549acd19e7fc225276f78374ac1600496bungeman            sk_sp<StructB> b;
325c901c11549acd19e7fc225276f78374ac1600496bungeman        };
326c901c11549acd19e7fc225276f78374ac1600496bungeman
327c901c11549acd19e7fc225276f78374ac1600496bungeman        struct StructB : public SkRefCnt {
328c901c11549acd19e7fc225276f78374ac1600496bungeman            sk_sp<StructA> a;
329fc6c37b981daeece7474ce61070c707c37eefa62Mike Klein            ~StructB() override {} // Some clang versions don't emit this implicitly.
330c901c11549acd19e7fc225276f78374ac1600496bungeman        };
331c901c11549acd19e7fc225276f78374ac1600496bungeman
332c901c11549acd19e7fc225276f78374ac1600496bungeman        // Create a reference cycle.
333c901c11549acd19e7fc225276f78374ac1600496bungeman        StructA* a = new StructA;
334c901c11549acd19e7fc225276f78374ac1600496bungeman        a->b.reset(new StructB);
335c901c11549acd19e7fc225276f78374ac1600496bungeman        a->b->a.reset(a);
336c901c11549acd19e7fc225276f78374ac1600496bungeman
337c901c11549acd19e7fc225276f78374ac1600496bungeman        // Break the cycle by calling reset(). This will cause |a| (and hence, |a.b|)
338c901c11549acd19e7fc225276f78374ac1600496bungeman        // to be deleted before the call to reset() returns. This tests that the
339c901c11549acd19e7fc225276f78374ac1600496bungeman        // implementation of sk_sp::reset() doesn't access |this| after it
340c901c11549acd19e7fc225276f78374ac1600496bungeman        // deletes the underlying pointer. This behaviour is consistent with the
341c901c11549acd19e7fc225276f78374ac1600496bungeman        // definition of unique_ptr::reset in C++11.
342c901c11549acd19e7fc225276f78374ac1600496bungeman        a->b.reset();
343c901c11549acd19e7fc225276f78374ac1600496bungeman    }
344bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed}
345bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed
346ffa39e02bc34a33c23fcccd61b781b5d05a980d3halcanarynamespace {
347ffa39e02bc34a33c23fcccd61b781b5d05a980d3halcanarystruct FooAbstract : public SkRefCnt {
348ffa39e02bc34a33c23fcccd61b781b5d05a980d3halcanary    virtual void f() = 0;
349ffa39e02bc34a33c23fcccd61b781b5d05a980d3halcanary};
350ffa39e02bc34a33c23fcccd61b781b5d05a980d3halcanarystruct FooConcrete : public FooAbstract {
351ffa39e02bc34a33c23fcccd61b781b5d05a980d3halcanary    void f() override {}
352ffa39e02bc34a33c23fcccd61b781b5d05a980d3halcanary};
353ffa39e02bc34a33c23fcccd61b781b5d05a980d3halcanary}
354ffa39e02bc34a33c23fcccd61b781b5d05a980d3halcanarystatic sk_sp<FooAbstract> make_foo() {
355ffa39e02bc34a33c23fcccd61b781b5d05a980d3halcanary    // can not cast FooConcrete to FooAbstract.
356ffa39e02bc34a33c23fcccd61b781b5d05a980d3halcanary    // can cast FooConcrete* to FooAbstract*.
357ffa39e02bc34a33c23fcccd61b781b5d05a980d3halcanary    return sk_make_sp<FooConcrete>();
358ffa39e02bc34a33c23fcccd61b781b5d05a980d3halcanary}
359ffa39e02bc34a33c23fcccd61b781b5d05a980d3halcanaryDEF_TEST(sk_make_sp, r) {
360ffa39e02bc34a33c23fcccd61b781b5d05a980d3halcanary    auto x = make_foo();
361ffa39e02bc34a33c23fcccd61b781b5d05a980d3halcanary}
362941da9d66171bd8efd2f6c5e25ff90c8c69885c1reed
363941da9d66171bd8efd2f6c5e25ff90c8c69885c1reed// Test that reset() "adopts" ownership from the caller, even if we are given the same ptr twice
364941da9d66171bd8efd2f6c5e25ff90c8c69885c1reed//
365941da9d66171bd8efd2f6c5e25ff90c8c69885c1reedDEF_TEST(sk_sp_reset, r) {
366941da9d66171bd8efd2f6c5e25ff90c8c69885c1reed    SkRefCnt* rc = new SkRefCnt;
367941da9d66171bd8efd2f6c5e25ff90c8c69885c1reed    REPORTER_ASSERT(r, rc->unique());
368941da9d66171bd8efd2f6c5e25ff90c8c69885c1reed
369941da9d66171bd8efd2f6c5e25ff90c8c69885c1reed    sk_sp<SkRefCnt> sp;
370941da9d66171bd8efd2f6c5e25ff90c8c69885c1reed    sp.reset(rc);
371941da9d66171bd8efd2f6c5e25ff90c8c69885c1reed    // We have transfered our ownership over to sp
372941da9d66171bd8efd2f6c5e25ff90c8c69885c1reed    REPORTER_ASSERT(r, rc->unique());
373941da9d66171bd8efd2f6c5e25ff90c8c69885c1reed
374941da9d66171bd8efd2f6c5e25ff90c8c69885c1reed    rc->ref();  // now "rc" is also an owner
375941da9d66171bd8efd2f6c5e25ff90c8c69885c1reed    REPORTER_ASSERT(r, !rc->unique());
376941da9d66171bd8efd2f6c5e25ff90c8c69885c1reed
377941da9d66171bd8efd2f6c5e25ff90c8c69885c1reed    sp.reset(rc);   // this should transfer our ownership over to sp
378941da9d66171bd8efd2f6c5e25ff90c8c69885c1reed    REPORTER_ASSERT(r, rc->unique());
379941da9d66171bd8efd2f6c5e25ff90c8c69885c1reed}
380647cc8474828202c98d540f799742e3074a2aacereed
381647cc8474828202c98d540f799742e3074a2aacereedDEF_TEST(sk_sp_ref, r) {
382647cc8474828202c98d540f799742e3074a2aacereed    SkRefCnt* rc = new SkRefCnt;
383647cc8474828202c98d540f799742e3074a2aacereed    REPORTER_ASSERT(r, rc->unique());
384647cc8474828202c98d540f799742e3074a2aacereed
385647cc8474828202c98d540f799742e3074a2aacereed    {
386647cc8474828202c98d540f799742e3074a2aacereed        sk_sp<SkRefCnt> sp = sk_ref_sp(rc);
387647cc8474828202c98d540f799742e3074a2aacereed        REPORTER_ASSERT(r, !rc->unique());
388647cc8474828202c98d540f799742e3074a2aacereed    }
389647cc8474828202c98d540f799742e3074a2aacereed
390647cc8474828202c98d540f799742e3074a2aacereed    REPORTER_ASSERT(r, rc->unique());
391647cc8474828202c98d540f799742e3074a2aacereed    rc->unref();
392647cc8474828202c98d540f799742e3074a2aacereed}
393