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 "SkTRefArray.h"
10#include "SkThreadUtils.h"
11#include "SkTypes.h"
12#include "SkWeakRefCnt.h"
13#include "Test.h"
14
15class InstCounterClass {
16public:
17    InstCounterClass() { fCount = gInstCounter++; }
18    InstCounterClass(const InstCounterClass& src) {
19        fCount = src.fCount;
20        gInstCounter += 1;
21    }
22    virtual ~InstCounterClass() { gInstCounter -= 1; }
23
24    static int gInstCounter;
25    int fCount;
26};
27
28int InstCounterClass::gInstCounter;
29
30static void test_refarray(skiatest::Reporter* reporter) {
31    REPORTER_ASSERT(reporter, 0 == InstCounterClass::gInstCounter);
32
33    const int N = 10;
34    SkTRefArray<InstCounterClass>* array = SkTRefArray<InstCounterClass>::Create(N);
35
36    REPORTER_ASSERT(reporter, 1 == array->getRefCnt());
37    REPORTER_ASSERT(reporter, N == array->count());
38
39    REPORTER_ASSERT(reporter, N == InstCounterClass::gInstCounter);
40    array->unref();
41    REPORTER_ASSERT(reporter, 0 == InstCounterClass::gInstCounter);
42
43    // Now test the copy factory
44
45    int i;
46    InstCounterClass* src = new InstCounterClass[N];
47    REPORTER_ASSERT(reporter, N == InstCounterClass::gInstCounter);
48    for (i = 0; i < N; ++i) {
49        REPORTER_ASSERT(reporter, i == src[i].fCount);
50    }
51
52    array = SkTRefArray<InstCounterClass>::Create(src, N);
53    REPORTER_ASSERT(reporter, 1 == array->getRefCnt());
54    REPORTER_ASSERT(reporter, N == array->count());
55
56    REPORTER_ASSERT(reporter, 2*N == InstCounterClass::gInstCounter);
57    for (i = 0; i < N; ++i) {
58        REPORTER_ASSERT(reporter, i == (*array)[i].fCount);
59    }
60
61    delete[] src;
62    REPORTER_ASSERT(reporter, N == InstCounterClass::gInstCounter);
63
64    for (i = 0; i < N; ++i) {
65        REPORTER_ASSERT(reporter, i == (*array)[i].fCount);
66    }
67    array->unref();
68    REPORTER_ASSERT(reporter, 0 == InstCounterClass::gInstCounter);
69}
70
71static void bounce_ref(void* data) {
72    SkRefCnt* ref = static_cast<SkRefCnt*>(data);
73    for (int i = 0; i < 100000; ++i) {
74        ref->ref();
75        ref->unref();
76    }
77}
78
79static void test_refCnt(skiatest::Reporter* reporter) {
80    SkRefCnt* ref = new SkRefCnt();
81
82    SkThread thing1(bounce_ref, ref);
83    SkThread thing2(bounce_ref, ref);
84
85    thing1.setProcessorAffinity(0);
86    thing2.setProcessorAffinity(23);
87
88    SkASSERT(thing1.start());
89    SkASSERT(thing2.start());
90
91    thing1.join();
92    thing2.join();
93
94    REPORTER_ASSERT(reporter, ref->getRefCnt() == 1);
95    ref->unref();
96}
97
98static void bounce_weak_ref(void* data) {
99    SkWeakRefCnt* ref = static_cast<SkWeakRefCnt*>(data);
100    for (int i = 0; i < 100000; ++i) {
101        if (ref->try_ref()) {
102            ref->unref();
103        }
104    }
105}
106
107static void bounce_weak_weak_ref(void* data) {
108    SkWeakRefCnt* ref = static_cast<SkWeakRefCnt*>(data);
109    for (int i = 0; i < 100000; ++i) {
110        ref->weak_ref();
111        ref->weak_unref();
112    }
113}
114
115static void test_weakRefCnt(skiatest::Reporter* reporter) {
116    SkWeakRefCnt* ref = new SkWeakRefCnt();
117
118    SkThread thing1(bounce_ref, ref);
119    SkThread thing2(bounce_ref, ref);
120    SkThread thing3(bounce_weak_ref, ref);
121    SkThread thing4(bounce_weak_weak_ref, ref);
122
123    thing1.setProcessorAffinity(0);
124    thing2.setProcessorAffinity(23);
125    thing3.setProcessorAffinity(2);
126    thing4.setProcessorAffinity(17);
127
128    SkASSERT(thing1.start());
129    SkASSERT(thing2.start());
130    SkASSERT(thing3.start());
131    SkASSERT(thing4.start());
132
133    thing1.join();
134    thing2.join();
135    thing3.join();
136    thing4.join();
137
138    REPORTER_ASSERT(reporter, ref->getRefCnt() == 1);
139    REPORTER_ASSERT(reporter, ref->getWeakCnt() == 1);
140    ref->unref();
141}
142
143DEF_TEST(RefCnt, reporter) {
144    test_refCnt(reporter);
145    test_weakRefCnt(reporter);
146    test_refarray(reporter);
147}
148