blob: 04269445276598bfd004a35e04bf99bed1d9c0a1 [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) {
robertphillips@google.comb74af872012-06-27 19:41:42 +000051#ifdef SK_ENABLE_INST_COUNT
bsalomon@google.com4da34e32012-06-19 15:40:27 +000052 SkASSERT(0 == GetInstanceCount());
robertphillips@google.comb74af872012-06-27 19:41:42 +000053#endif
bsalomon@google.com4da34e32012-06-19 15:40:27 +000054 GrMemoryPool* pool = new GrMemoryPool(preallocSize, minAllocSize);
55 gPool.reset(pool);
56 }
57
58 static void ResetAllocator() {
robertphillips@google.comb74af872012-06-27 19:41:42 +000059#ifdef SK_ENABLE_INST_COUNT
bsalomon@google.com4da34e32012-06-19 15:40:27 +000060 SkASSERT(0 == GetInstanceCount());
robertphillips@google.comb74af872012-06-27 19:41:42 +000061#endif
bsalomon@google.com4da34e32012-06-19 15:40:27 +000062 gPool.reset(NULL);
63 }
64
65private:
66 static SkTScopedPtr<GrMemoryPool> gPool;
67 char fChar;
68};
69SK_DEFINE_INST_COUNT(A);
70SkTScopedPtr<GrMemoryPool> A::gPool;
71
72class B : public A {
73public:
74 B() {};
75 virtual void setValues(int v) {
76 fDouble = static_cast<double>(v);
77 this->INHERITED::setValues(v);
78 }
79 virtual bool checkValues(int v) {
80 return fDouble == static_cast<double>(v) &&
81 this->INHERITED::checkValues(v);
82 }
83 virtual ~B() {};
84
85private:
86 double fDouble;
87
88 typedef A INHERITED;
89};
90
91class C : public A {
92public:
93 C() {};
94 virtual void setValues(int v) {
95 fInt64 = static_cast<int64_t>(v);
96 this->INHERITED::setValues(v);
97 }
98 virtual bool checkValues(int v) {
99 return fInt64 == static_cast<int64_t>(v) &&
100 this->INHERITED::checkValues(v);
101 }
102 virtual ~C() {};
103
104private:
105 int64_t fInt64;
106
107 typedef A INHERITED;
108};
109
110// D derives from C and owns a dynamically created B
111class D : public C {
112public:
113 D() {
114 fB = new B();
115 }
116 virtual void setValues(int v) {
117 fVoidStar = reinterpret_cast<void*>(v);
118 this->INHERITED::setValues(v);
119 fB->setValues(v);
120 }
121 virtual bool checkValues(int v) {
122 return fVoidStar == reinterpret_cast<void*>(v) &&
123 fB->checkValues(v) &&
124 this->INHERITED::checkValues(v);
125 }
126 virtual ~D() {
127 delete fB;
128 }
129private:
130 void* fVoidStar;
131 B* fB;
132
133 typedef C INHERITED;
134};
135
136class E : public A {
137public:
138 E() {}
139 virtual void setValues(int v) {
140 for (size_t i = 0; i < SK_ARRAY_COUNT(fIntArray); ++i) {
141 fIntArray[i] = v;
142 }
143 this->INHERITED::setValues(v);
144 }
145 virtual bool checkValues(int v) {
146 bool ok = true;
147 for (size_t i = 0; ok && i < SK_ARRAY_COUNT(fIntArray); ++i) {
148 if (fIntArray[i] != v) {
149 ok = false;
150 }
151 }
152 return ok && this->INHERITED::checkValues(v);
153 }
154 virtual ~E() {}
155private:
156 int fIntArray[20];
157
158 typedef A INHERITED;
159};
160
161A* A::Create(SkRandom* r) {
162 switch (r->nextRangeU(0, 4)) {
163 case 0:
164 return new A;
165 case 1:
166 return new B;
167 case 2:
168 return new C;
169 case 3:
170 return new D;
171 case 4:
172 return new E;
173 default:
174 // suppress warning
175 return NULL;
176 }
177}
178}
179struct Rec {
180 A* fInstance;
181 int fValue;
182};
183
184static void test_memory_pool(skiatest::Reporter* reporter) {
185 // prealloc and min alloc sizes for the pool
186 static const size_t gSizes[][2] = {
187 {0, 0},
188 {10 * sizeof(A), 20 * sizeof(A)},
189 {100 * sizeof(A), 100 * sizeof(A)},
190 {500 * sizeof(A), 500 * sizeof(A)},
191 {10000 * sizeof(A), 0},
192 {1, 100 * sizeof(A)},
193 };
194 // different percentages of creation vs deletion
195 static const float gCreateFraction[] = {1.f, .95f, 0.75f, .5f};
196 // number of create/destroys per test
197 static const int kNumIters = 20000;
198 // check that all the values stored in A objects are correct after this
199 // number of iterations
200 static const int kCheckPeriod = 500;
201
202 SkRandom r;
203 for (size_t s = 0; s < SK_ARRAY_COUNT(gSizes); ++s) {
204 A::SetAllocator(gSizes[s][0], gSizes[s][1]);
205 for (size_t c = 0; c < SK_ARRAY_COUNT(gCreateFraction); ++c) {
206 SkTDArray<Rec> instanceRecs;
207 for (int i = 0; i < kNumIters; ++i) {
208 float createOrDestroy = r.nextUScalar1();
209 if (createOrDestroy < gCreateFraction[c] ||
210 0 == instanceRecs.count()) {
211 Rec* rec = instanceRecs.append();
212 rec->fInstance = A::Create(&r);
213 rec->fValue = static_cast<int>(r.nextU());
214 rec->fInstance->setValues(rec->fValue);
215 } else {
216 int d = r.nextRangeU(0, instanceRecs.count() - 1);
217 Rec& rec = instanceRecs[d];
218 REPORTER_ASSERT(reporter, rec.fInstance->checkValues(rec.fValue));
219 delete rec.fInstance;
220 instanceRecs.removeShuffle(d);
221 }
222 if (0 == i % kCheckPeriod) {
223 for (int r = 0; r < instanceRecs.count(); ++r) {
224 Rec& rec = instanceRecs[r];
225 REPORTER_ASSERT(reporter, rec.fInstance->checkValues(rec.fValue));
226 }
227 }
228 }
229 for (int i = 0; i < instanceRecs.count(); ++i) {
230 Rec& rec = instanceRecs[i];
231 REPORTER_ASSERT(reporter, rec.fInstance->checkValues(rec.fValue));
232 delete rec.fInstance;
233 }
234#ifdef SK_DEBUG
235 REPORTER_ASSERT(reporter, !A::GetInstanceCount());
236#endif
237 }
238 }
239}
240
241#include "TestClassDef.h"
242DEFINE_TESTCLASS("GrMemoryPool", GrMemoryPoolClass, test_memory_pool)
243