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