blob: f5527e9b356371d3ff9bbee8c2d885cb75401c69 [file] [log] [blame]
bsalomon@google.com4da34e32012-06-19 15:40:27 +00001/*
2 * Copyright 2011 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 "Test.h"
9#include "GrMemoryPool.h"
10#include "SkRandom.h"
11#include "SkTDArray.h"
12#include "SkTScopedPtr.h"
13#include "SkInstCnt.h"
14
15namespace {
16// A is the top of an inheritance tree of classes that overload op new and
17// and delete to use a GrMemoryPool. The objects have values of different types
18// that can be set and checked.
19class A {
20public:
21 A() {};
22 virtual void setValues(int v) {
23 fChar = static_cast<char>(v);
24 }
25 virtual bool checkValues(int v) {
26 return fChar == static_cast<char>(v);
27 }
28 virtual ~A() {};
29
30 void* operator new(size_t size) {
31 if (!gPool.get()) {
32 return ::operator new(size);
33 } else {
34 return gPool->allocate(size);
35 }
36 }
37
38 void operator delete(void* p) {
39 if (!gPool.get()) {
40 ::operator delete(p);
41 } else {
42 return gPool->release(p);
43 }
44 }
45
46 SK_DECLARE_INST_COUNT_ROOT(A);
47
48 static A* Create(SkRandom* r);
49
50 static void SetAllocator(size_t preallocSize, size_t minAllocSize) {
51 SkASSERT(0 == GetInstanceCount());
52 GrMemoryPool* pool = new GrMemoryPool(preallocSize, minAllocSize);
53 gPool.reset(pool);
54 }
55
56 static void ResetAllocator() {
57 SkASSERT(0 == GetInstanceCount());
58 gPool.reset(NULL);
59 }
60
61private:
62 static SkTScopedPtr<GrMemoryPool> gPool;
63 char fChar;
64};
65SK_DEFINE_INST_COUNT(A);
66SkTScopedPtr<GrMemoryPool> A::gPool;
67
68class B : public A {
69public:
70 B() {};
71 virtual void setValues(int v) {
72 fDouble = static_cast<double>(v);
73 this->INHERITED::setValues(v);
74 }
75 virtual bool checkValues(int v) {
76 return fDouble == static_cast<double>(v) &&
77 this->INHERITED::checkValues(v);
78 }
79 virtual ~B() {};
80
81private:
82 double fDouble;
83
84 typedef A INHERITED;
85};
86
87class C : public A {
88public:
89 C() {};
90 virtual void setValues(int v) {
91 fInt64 = static_cast<int64_t>(v);
92 this->INHERITED::setValues(v);
93 }
94 virtual bool checkValues(int v) {
95 return fInt64 == static_cast<int64_t>(v) &&
96 this->INHERITED::checkValues(v);
97 }
98 virtual ~C() {};
99
100private:
101 int64_t fInt64;
102
103 typedef A INHERITED;
104};
105
106// D derives from C and owns a dynamically created B
107class D : public C {
108public:
109 D() {
110 fB = new B();
111 }
112 virtual void setValues(int v) {
113 fVoidStar = reinterpret_cast<void*>(v);
114 this->INHERITED::setValues(v);
115 fB->setValues(v);
116 }
117 virtual bool checkValues(int v) {
118 return fVoidStar == reinterpret_cast<void*>(v) &&
119 fB->checkValues(v) &&
120 this->INHERITED::checkValues(v);
121 }
122 virtual ~D() {
123 delete fB;
124 }
125private:
126 void* fVoidStar;
127 B* fB;
128
129 typedef C INHERITED;
130};
131
132class E : public A {
133public:
134 E() {}
135 virtual void setValues(int v) {
136 for (size_t i = 0; i < SK_ARRAY_COUNT(fIntArray); ++i) {
137 fIntArray[i] = v;
138 }
139 this->INHERITED::setValues(v);
140 }
141 virtual bool checkValues(int v) {
142 bool ok = true;
143 for (size_t i = 0; ok && i < SK_ARRAY_COUNT(fIntArray); ++i) {
144 if (fIntArray[i] != v) {
145 ok = false;
146 }
147 }
148 return ok && this->INHERITED::checkValues(v);
149 }
150 virtual ~E() {}
151private:
152 int fIntArray[20];
153
154 typedef A INHERITED;
155};
156
157A* A::Create(SkRandom* r) {
158 switch (r->nextRangeU(0, 4)) {
159 case 0:
160 return new A;
161 case 1:
162 return new B;
163 case 2:
164 return new C;
165 case 3:
166 return new D;
167 case 4:
168 return new E;
169 default:
170 // suppress warning
171 return NULL;
172 }
173}
174}
175struct Rec {
176 A* fInstance;
177 int fValue;
178};
179
180static void test_memory_pool(skiatest::Reporter* reporter) {
181 // prealloc and min alloc sizes for the pool
182 static const size_t gSizes[][2] = {
183 {0, 0},
184 {10 * sizeof(A), 20 * sizeof(A)},
185 {100 * sizeof(A), 100 * sizeof(A)},
186 {500 * sizeof(A), 500 * sizeof(A)},
187 {10000 * sizeof(A), 0},
188 {1, 100 * sizeof(A)},
189 };
190 // different percentages of creation vs deletion
191 static const float gCreateFraction[] = {1.f, .95f, 0.75f, .5f};
192 // number of create/destroys per test
193 static const int kNumIters = 20000;
194 // check that all the values stored in A objects are correct after this
195 // number of iterations
196 static const int kCheckPeriod = 500;
197
198 SkRandom r;
199 for (size_t s = 0; s < SK_ARRAY_COUNT(gSizes); ++s) {
200 A::SetAllocator(gSizes[s][0], gSizes[s][1]);
201 for (size_t c = 0; c < SK_ARRAY_COUNT(gCreateFraction); ++c) {
202 SkTDArray<Rec> instanceRecs;
203 for (int i = 0; i < kNumIters; ++i) {
204 float createOrDestroy = r.nextUScalar1();
205 if (createOrDestroy < gCreateFraction[c] ||
206 0 == instanceRecs.count()) {
207 Rec* rec = instanceRecs.append();
208 rec->fInstance = A::Create(&r);
209 rec->fValue = static_cast<int>(r.nextU());
210 rec->fInstance->setValues(rec->fValue);
211 } else {
212 int d = r.nextRangeU(0, instanceRecs.count() - 1);
213 Rec& rec = instanceRecs[d];
214 REPORTER_ASSERT(reporter, rec.fInstance->checkValues(rec.fValue));
215 delete rec.fInstance;
216 instanceRecs.removeShuffle(d);
217 }
218 if (0 == i % kCheckPeriod) {
219 for (int r = 0; r < instanceRecs.count(); ++r) {
220 Rec& rec = instanceRecs[r];
221 REPORTER_ASSERT(reporter, rec.fInstance->checkValues(rec.fValue));
222 }
223 }
224 }
225 for (int i = 0; i < instanceRecs.count(); ++i) {
226 Rec& rec = instanceRecs[i];
227 REPORTER_ASSERT(reporter, rec.fInstance->checkValues(rec.fValue));
228 delete rec.fInstance;
229 }
230#ifdef SK_DEBUG
231 REPORTER_ASSERT(reporter, !A::GetInstanceCount());
232#endif
233 }
234 }
235}
236
237#include "TestClassDef.h"
238DEFINE_TESTCLASS("GrMemoryPool", GrMemoryPoolClass, test_memory_pool)
239