1 /*-------------------------------------------------------------------------
2 * drawElements C++ Base Library
3 * -----------------------------
4 *
5 * Copyright 2014 The Android Open Source Project
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 *//*!
20 * \file
21 * \brief Shared pointer.
22 *//*--------------------------------------------------------------------*/
23
24 #include "deSharedPtr.hpp"
25 #include "deThread.hpp"
26 #include "deClock.h"
27
28 #include <exception>
29
30 namespace de
31 {
32
33 namespace
34 {
35
36 enum
37 {
38 THREAD_TEST_TIME = 200 * 1000
39 };
40
41 class Object
42 {
43 public:
Object(bool & exists)44 Object(bool &exists) : m_exists(exists)
45 {
46 m_exists = true;
47 }
48
~Object(void)49 virtual ~Object(void)
50 {
51 m_exists = false;
52 }
53
54 private:
55 bool &m_exists;
56 };
57
58 class DerivedObject : public Object
59 {
60 public:
DerivedObject(bool & exists)61 DerivedObject(bool &exists) : Object(exists)
62 {
63 }
64 };
65
66 class SharedPtrTestThread : public Thread
67 {
68 public:
SharedPtrTestThread(const SharedPtr<Object> & ptr,const bool & exists)69 SharedPtrTestThread(const SharedPtr<Object> &ptr, const bool &exists) : m_ptr(ptr), m_exists(exists)
70 {
71 }
72
run(void)73 void run(void)
74 {
75 uint64_t startTime = deGetMicroseconds();
76 uint64_t cnt = 0;
77
78 for (;; cnt++)
79 {
80 if (((cnt & (1 << 14)) != 0) && (deGetMicroseconds() - startTime >= THREAD_TEST_TIME))
81 break;
82
83 {
84 SharedPtr<Object> ptrA(m_ptr);
85 {
86 SharedPtr<Object> ptrB;
87 ptrB = ptrA;
88 ptrA = SharedPtr<Object>();
89 }
90 }
91 DE_TEST_ASSERT(m_exists);
92 }
93 }
94
95 private:
96 SharedPtr<Object> m_ptr;
97 const bool &m_exists;
98 };
99
100 class WeakPtrTestThread : public Thread
101 {
102 public:
WeakPtrTestThread(const SharedPtr<Object> & ptr,const bool & exists)103 WeakPtrTestThread(const SharedPtr<Object> &ptr, const bool &exists) : m_ptr(ptr), m_exists(exists)
104 {
105 }
106
run(void)107 void run(void)
108 {
109 uint64_t startTime = deGetMicroseconds();
110 uint64_t cnt = 0;
111
112 for (;; cnt++)
113 {
114 if (((cnt & (1 << 14)) != 0) && (deGetMicroseconds() - startTime >= THREAD_TEST_TIME))
115 break;
116
117 {
118 WeakPtr<Object> ptrA(m_ptr);
119 {
120 WeakPtr<Object> ptrB;
121 ptrB = ptrA;
122 ptrA = SharedPtr<Object>();
123 }
124 }
125 DE_TEST_ASSERT(m_exists);
126 }
127 }
128
129 private:
130 SharedPtr<Object> m_ptr;
131 const bool &m_exists;
132 };
133
makeObject(bool & exists)134 SharedPtr<Object> makeObject(bool &exists)
135 {
136 return SharedPtr<Object>(new Object(exists));
137 }
138
139 struct CustomDeleter
140 {
CustomDeleterde::__anon7181c7410111::CustomDeleter141 CustomDeleter(bool *called) : m_called(called)
142 {
143 }
144
operator ()de::__anon7181c7410111::CustomDeleter145 void operator()(Object *ptr)
146 {
147 DE_TEST_ASSERT(!*m_called);
148 delete ptr;
149 *m_called = true;
150 }
151
152 bool *m_called;
153 };
154
155 } // namespace
156
SharedPtr_selfTest(void)157 void SharedPtr_selfTest(void)
158 {
159 // Empty pointer test.
160 {
161 SharedPtr<Object> ptr;
162 DE_TEST_ASSERT(ptr.get() == DE_NULL);
163 DE_TEST_ASSERT(!ptr);
164 }
165
166 // Empty pointer copy.
167 {
168 SharedPtr<Object> ptrA;
169 SharedPtr<Object> ptrB(ptrA);
170 DE_TEST_ASSERT(ptrB.get() == DE_NULL);
171 }
172
173 // Empty pointer assignment.
174 {
175 SharedPtr<Object> ptrA;
176 SharedPtr<Object> ptrB;
177 ptrB = ptrA;
178 ptrB = *&ptrB;
179 }
180
181 // Basic test.
182 {
183 bool exists = false;
184 {
185 SharedPtr<Object> ptr(new Object(exists));
186 DE_TEST_ASSERT(exists);
187 DE_TEST_ASSERT(ptr.get() != DE_NULL);
188 DE_TEST_ASSERT(ptr);
189 }
190 DE_TEST_ASSERT(!exists);
191 }
192
193 // Exception test.
194 {
195 bool exists = false;
196 try
197 {
198 SharedPtr<Object> ptr(new Object(exists));
199 DE_TEST_ASSERT(exists);
200 DE_TEST_ASSERT(ptr.get() != DE_NULL);
201 throw std::exception();
202 }
203 catch (const std::exception &)
204 {
205 DE_TEST_ASSERT(!exists);
206 }
207 DE_TEST_ASSERT(!exists);
208 }
209
210 // Expression test.
211 {
212 bool exists = false;
213 bool test = (SharedPtr<Object>(new Object(exists))).get() != DE_NULL && exists;
214 DE_TEST_ASSERT(!exists);
215 DE_TEST_ASSERT(test);
216 }
217
218 // Assignment test.
219 {
220 bool exists = false;
221 SharedPtr<Object> ptr(new Object(exists));
222 DE_TEST_ASSERT(exists);
223 ptr = SharedPtr<Object>();
224 DE_TEST_ASSERT(!exists);
225 }
226
227 // Self-assignment test.
228 {
229 bool exists = false;
230 {
231 SharedPtr<Object> ptr(new Object(exists));
232 DE_TEST_ASSERT(exists);
233 DE_TEST_ASSERT(ptr.get() != DE_NULL);
234 ptr = *&ptr;
235 }
236 DE_TEST_ASSERT(!exists);
237 }
238
239 // Basic multi-reference via copy ctor.
240 {
241 bool exists = false;
242 {
243 SharedPtr<Object> ptrA(new Object(exists));
244 DE_TEST_ASSERT(exists);
245 {
246 SharedPtr<Object> ptrB(ptrA);
247 DE_TEST_ASSERT(exists);
248 }
249 DE_TEST_ASSERT(exists);
250 }
251 DE_TEST_ASSERT(!exists);
252 }
253
254 // Basic multi-reference via assignment to empty.
255 {
256 bool exists = false;
257 {
258 SharedPtr<Object> ptrA(new Object(exists));
259 DE_TEST_ASSERT(exists);
260 {
261 SharedPtr<Object> ptrB;
262 ptrB = ptrA;
263 DE_TEST_ASSERT(exists);
264 }
265 DE_TEST_ASSERT(exists);
266 }
267 DE_TEST_ASSERT(!exists);
268 }
269
270 // Multi-reference via assignment to non-empty.
271 {
272 bool existsA = false;
273 bool existsB = false;
274 {
275 SharedPtr<Object> ptrA(new Object(existsA));
276 DE_TEST_ASSERT(existsA);
277 {
278 SharedPtr<Object> ptrB(new Object(existsB));
279 DE_TEST_ASSERT(existsB);
280 ptrA = ptrB;
281 DE_TEST_ASSERT(!existsA);
282 DE_TEST_ASSERT(existsB);
283 }
284 DE_TEST_ASSERT(existsB);
285 }
286 DE_TEST_ASSERT(!existsB);
287 }
288
289 // Return from function.
290 {
291 bool exists = false;
292 {
293 SharedPtr<Object> ptr;
294 ptr = makeObject(exists);
295 DE_TEST_ASSERT(exists);
296 }
297 DE_TEST_ASSERT(!exists);
298 }
299
300 // Equality comparison.
301 {
302 bool existsA = false;
303 bool existsB = false;
304 SharedPtr<Object> ptrA(new Object(existsA));
305 SharedPtr<Object> ptrB(new Object(existsB));
306 SharedPtr<Object> ptrC(ptrA);
307
308 DE_TEST_ASSERT(ptrA == ptrA);
309 DE_TEST_ASSERT(ptrA != ptrB);
310 DE_TEST_ASSERT(ptrA == ptrC);
311 DE_TEST_ASSERT(ptrC != ptrB);
312 }
313
314 // Conversion via assignment.
315 {
316 bool exists = false;
317 {
318 SharedPtr<Object> basePtr;
319 {
320 SharedPtr<DerivedObject> derivedPtr(new DerivedObject(exists));
321 DE_TEST_ASSERT(exists);
322 basePtr = derivedPtr;
323 DE_TEST_ASSERT(exists);
324 }
325 DE_TEST_ASSERT(exists);
326 }
327 DE_TEST_ASSERT(!exists);
328 }
329
330 // Conversion via copy ctor.
331 {
332 bool exists = false;
333 {
334 SharedPtr<DerivedObject> derivedPtr(new DerivedObject(exists));
335 SharedPtr<Object> basePtr(derivedPtr);
336 DE_TEST_ASSERT(exists);
337 derivedPtr = SharedPtr<DerivedObject>();
338 DE_TEST_ASSERT(exists);
339 }
340 DE_TEST_ASSERT(!exists);
341 }
342
343 // Explicit conversion operator.
344 {
345 bool exists = false;
346 {
347 SharedPtr<DerivedObject> derivedPtr(new DerivedObject(exists));
348 DE_TEST_ASSERT(exists);
349
350 SharedPtr<Object> basePtr = (SharedPtr<Object>)(derivedPtr);
351 derivedPtr = SharedPtr<DerivedObject>();
352 DE_TEST_ASSERT(exists);
353 }
354 DE_TEST_ASSERT(!exists);
355 }
356
357 // Basic weak reference.
358 {
359 bool exists = false;
360 SharedPtr<Object> ptr(new Object(exists));
361 DE_TEST_ASSERT(exists);
362
363 WeakPtr<Object> weakPtr(ptr);
364 try
365 {
366 SharedPtr<Object> newRef(weakPtr);
367 DE_TEST_ASSERT(exists);
368 }
369 catch (const DeadReferenceException &)
370 {
371 DE_TEST_ASSERT(false);
372 }
373
374 ptr = SharedPtr<Object>();
375 DE_TEST_ASSERT(!exists);
376 try
377 {
378 SharedPtr<Object> newRef(weakPtr);
379 DE_TEST_ASSERT(false);
380 }
381 catch (const DeadReferenceException &)
382 {
383 }
384 }
385
386 // Basic SharedPtr threaded test.
387 {
388 bool exists = false;
389 {
390 SharedPtr<Object> ptr(new Object(exists));
391
392 SharedPtrTestThread threadA(ptr, exists);
393 SharedPtrTestThread threadB(ptr, exists);
394
395 threadA.start();
396 threadB.start();
397
398 threadA.join();
399 threadB.join();
400 DE_TEST_ASSERT(exists);
401 }
402 DE_TEST_ASSERT(!exists);
403 }
404
405 // Basic WeakPtr threaded test.
406 {
407 bool exists = false;
408 {
409 SharedPtr<Object> ptr(new Object(exists));
410 WeakPtrTestThread threadA(ptr, exists);
411 WeakPtrTestThread threadB(ptr, exists);
412
413 threadA.start();
414 threadB.start();
415
416 threadA.join();
417 threadB.join();
418 DE_TEST_ASSERT(exists);
419 }
420 DE_TEST_ASSERT(!exists);
421 }
422
423 // Basic custom deleter.
424 {
425 bool exists = false;
426 bool deleterCalled = false;
427 {
428 SharedPtr<Object> ptr(new Object(exists), CustomDeleter(&deleterCalled));
429 DE_TEST_ASSERT(exists);
430 DE_TEST_ASSERT(!deleterCalled);
431 DE_TEST_ASSERT(ptr.get() != DE_NULL);
432 }
433 DE_TEST_ASSERT(!exists);
434 DE_TEST_ASSERT(deleterCalled);
435 }
436 }
437
438 } // namespace de
439