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)
45 : m_exists(exists)
46 {
47 m_exists = true;
48 }
49
~Object(void)50 virtual ~Object (void)
51 {
52 m_exists = false;
53 }
54
55 private:
56 bool& m_exists;
57 };
58
59 class DerivedObject : public Object
60 {
61 public:
DerivedObject(bool & exists)62 DerivedObject (bool& exists)
63 : Object(exists)
64 {
65 }
66 };
67
68 class SharedPtrTestThread : public Thread
69 {
70 public:
SharedPtrTestThread(const SharedPtr<Object> & ptr,const bool & exists)71 SharedPtrTestThread (const SharedPtr<Object>& ptr, const bool& exists)
72 : m_ptr (ptr)
73 , m_exists (exists)
74 {
75 }
76
run(void)77 void run (void)
78 {
79 deUint64 startTime = deGetMicroseconds();
80 deUint64 cnt = 0;
81
82 for (;; cnt++)
83 {
84 if (((cnt&(1<<14)) != 0) && (deGetMicroseconds()-startTime >= THREAD_TEST_TIME))
85 break;
86
87 {
88 SharedPtr<Object> ptrA(m_ptr);
89 {
90 SharedPtr<Object> ptrB;
91 ptrB = ptrA;
92 ptrA = SharedPtr<Object>();
93 }
94 }
95 DE_TEST_ASSERT(m_exists);
96 }
97 }
98
99 private:
100 SharedPtr<Object> m_ptr;
101 const bool& m_exists;
102 };
103
104 class WeakPtrTestThread : public Thread
105 {
106 public:
WeakPtrTestThread(const SharedPtr<Object> & ptr,const bool & exists)107 WeakPtrTestThread (const SharedPtr<Object>& ptr, const bool& exists)
108 : m_ptr (ptr)
109 , m_exists (exists)
110 {
111 }
112
run(void)113 void run (void)
114 {
115 deUint64 startTime = deGetMicroseconds();
116 deUint64 cnt = 0;
117
118 for (;; cnt++)
119 {
120 if (((cnt&(1<<14)) != 0) && (deGetMicroseconds()-startTime >= THREAD_TEST_TIME))
121 break;
122
123 {
124 WeakPtr<Object> ptrA(m_ptr);
125 {
126 WeakPtr<Object> ptrB;
127 ptrB = ptrA;
128 ptrA = SharedPtr<Object>();
129 }
130 }
131 DE_TEST_ASSERT(m_exists);
132 }
133 }
134
135 private:
136 SharedPtr<Object> m_ptr;
137 const bool& m_exists;
138 };
139
makeObject(bool & exists)140 SharedPtr<Object> makeObject (bool& exists)
141 {
142 return SharedPtr<Object>(new Object(exists));
143 }
144
145 struct CustomDeleter
146 {
CustomDeleterde::__anon3bb4c8cf0111::CustomDeleter147 CustomDeleter (bool* called) : m_called(called) {}
148
operator ()de::__anon3bb4c8cf0111::CustomDeleter149 void operator() (Object* ptr)
150 {
151 DE_TEST_ASSERT(!*m_called);
152 delete ptr;
153 *m_called = true;
154 }
155
156 bool* m_called;
157 };
158
159 } // anonymous
160
SharedPtr_selfTest(void)161 void SharedPtr_selfTest (void)
162 {
163 // Empty pointer test.
164 {
165 SharedPtr<Object> ptr;
166 DE_TEST_ASSERT(ptr.get() == DE_NULL);
167 DE_TEST_ASSERT(!ptr);
168 }
169
170 // Empty pointer copy.
171 {
172 SharedPtr<Object> ptrA;
173 SharedPtr<Object> ptrB(ptrA);
174 DE_TEST_ASSERT(ptrB.get() == DE_NULL);
175 }
176
177 // Empty pointer assignment.
178 {
179 SharedPtr<Object> ptrA;
180 SharedPtr<Object> ptrB;
181 ptrB = ptrA;
182 ptrB = ptrB;
183 }
184
185 // Basic test.
186 {
187 bool exists = false;
188 {
189 SharedPtr<Object> ptr(new Object(exists));
190 DE_TEST_ASSERT(exists);
191 DE_TEST_ASSERT(ptr.get() != DE_NULL);
192 DE_TEST_ASSERT(ptr);
193 }
194 DE_TEST_ASSERT(!exists);
195 }
196
197 // Exception test.
198 {
199 bool exists = false;
200 try
201 {
202 SharedPtr<Object> ptr(new Object(exists));
203 DE_TEST_ASSERT(exists);
204 DE_TEST_ASSERT(ptr.get() != DE_NULL);
205 throw std::exception();
206 }
207 catch (const std::exception&)
208 {
209 DE_TEST_ASSERT(!exists);
210 }
211 DE_TEST_ASSERT(!exists);
212 }
213
214 // Expression test.
215 {
216 bool exists = false;
217 bool test = (SharedPtr<Object>(new Object(exists))).get() != DE_NULL && exists;
218 DE_TEST_ASSERT(!exists);
219 DE_TEST_ASSERT(test);
220 }
221
222 // Assignment test.
223 {
224 bool exists = false;
225 SharedPtr<Object> ptr(new Object(exists));
226 DE_TEST_ASSERT(exists);
227 ptr = SharedPtr<Object>();
228 DE_TEST_ASSERT(!exists);
229 }
230
231 // Self-assignment test.
232 {
233 bool exists = false;
234 {
235 SharedPtr<Object> ptr(new Object(exists));
236 DE_TEST_ASSERT(exists);
237 DE_TEST_ASSERT(ptr.get() != DE_NULL);
238 ptr = ptr;
239 }
240 DE_TEST_ASSERT(!exists);
241 }
242
243 // Basic multi-reference via copy ctor.
244 {
245 bool exists = false;
246 {
247 SharedPtr<Object> ptrA(new Object(exists));
248 DE_TEST_ASSERT(exists);
249 {
250 SharedPtr<Object> ptrB(ptrA);
251 DE_TEST_ASSERT(exists);
252 }
253 DE_TEST_ASSERT(exists);
254 }
255 DE_TEST_ASSERT(!exists);
256 }
257
258 // Basic multi-reference via assignment to empty.
259 {
260 bool exists = false;
261 {
262 SharedPtr<Object> ptrA(new Object(exists));
263 DE_TEST_ASSERT(exists);
264 {
265 SharedPtr<Object> ptrB;
266 ptrB = ptrA;
267 DE_TEST_ASSERT(exists);
268 }
269 DE_TEST_ASSERT(exists);
270 }
271 DE_TEST_ASSERT(!exists);
272 }
273
274 // Multi-reference via assignment to non-empty.
275 {
276 bool existsA = false;
277 bool existsB = false;
278 {
279 SharedPtr<Object> ptrA(new Object(existsA));
280 DE_TEST_ASSERT(existsA);
281 {
282 SharedPtr<Object> ptrB(new Object(existsB));
283 DE_TEST_ASSERT(existsB);
284 ptrA = ptrB;
285 DE_TEST_ASSERT(!existsA);
286 DE_TEST_ASSERT(existsB);
287 }
288 DE_TEST_ASSERT(existsB);
289 }
290 DE_TEST_ASSERT(!existsB);
291 }
292
293 // Return from function.
294 {
295 bool exists = false;
296 {
297 SharedPtr<Object> ptr;
298 ptr = makeObject(exists);
299 DE_TEST_ASSERT(exists);
300 }
301 DE_TEST_ASSERT(!exists);
302 }
303
304 // Equality comparison.
305 {
306 bool existsA = false;
307 bool existsB = false;
308 SharedPtr<Object> ptrA(new Object(existsA));
309 SharedPtr<Object> ptrB(new Object(existsB));
310 SharedPtr<Object> ptrC(ptrA);
311
312 DE_TEST_ASSERT(ptrA == ptrA);
313 DE_TEST_ASSERT(ptrA != ptrB);
314 DE_TEST_ASSERT(ptrA == ptrC);
315 DE_TEST_ASSERT(ptrC != ptrB);
316 }
317
318 // Conversion via assignment.
319 {
320 bool exists = false;
321 {
322 SharedPtr<Object> basePtr;
323 {
324 SharedPtr<DerivedObject> derivedPtr(new DerivedObject(exists));
325 DE_TEST_ASSERT(exists);
326 basePtr = derivedPtr;
327 DE_TEST_ASSERT(exists);
328 }
329 DE_TEST_ASSERT(exists);
330 }
331 DE_TEST_ASSERT(!exists);
332 }
333
334 // Conversion via copy ctor.
335 {
336 bool exists = false;
337 {
338 SharedPtr<DerivedObject> derivedPtr (new DerivedObject(exists));
339 SharedPtr<Object> basePtr (derivedPtr);
340 DE_TEST_ASSERT(exists);
341 derivedPtr = SharedPtr<DerivedObject>();
342 DE_TEST_ASSERT(exists);
343 }
344 DE_TEST_ASSERT(!exists);
345 }
346
347 // Explicit conversion operator.
348 {
349 bool exists = false;
350 {
351 SharedPtr<DerivedObject> derivedPtr (new DerivedObject(exists));
352 DE_TEST_ASSERT(exists);
353
354 SharedPtr<Object> basePtr = (SharedPtr<Object>)(derivedPtr);
355 derivedPtr = SharedPtr<DerivedObject>();
356 DE_TEST_ASSERT(exists);
357 }
358 DE_TEST_ASSERT(!exists);
359 }
360
361 // Basic weak reference.
362 {
363 bool exists = false;
364 SharedPtr<Object> ptr(new Object(exists));
365 DE_TEST_ASSERT(exists);
366
367 WeakPtr<Object> weakPtr(ptr);
368 try
369 {
370 SharedPtr<Object> newRef(weakPtr);
371 DE_TEST_ASSERT(exists);
372 }
373 catch (const DeadReferenceException&)
374 {
375 DE_TEST_ASSERT(false);
376 }
377
378 ptr = SharedPtr<Object>();
379 DE_TEST_ASSERT(!exists);
380 try
381 {
382 SharedPtr<Object> newRef(weakPtr);
383 DE_TEST_ASSERT(false);
384 }
385 catch (const DeadReferenceException&)
386 {
387 }
388 }
389
390 // Basic SharedPtr threaded test.
391 {
392 bool exists = false;
393 {
394 SharedPtr<Object> ptr(new Object(exists));
395
396 SharedPtrTestThread threadA(ptr, exists);
397 SharedPtrTestThread threadB(ptr, exists);
398
399 threadA.start();
400 threadB.start();
401
402 threadA.join();
403 threadB.join();
404 DE_TEST_ASSERT(exists);
405 }
406 DE_TEST_ASSERT(!exists);
407 }
408
409 // Basic WeakPtr threaded test.
410 {
411 bool exists = false;
412 {
413 SharedPtr<Object> ptr(new Object(exists));
414 WeakPtrTestThread threadA(ptr, exists);
415 WeakPtrTestThread threadB(ptr, exists);
416
417 threadA.start();
418 threadB.start();
419
420 threadA.join();
421 threadB.join();
422 DE_TEST_ASSERT(exists);
423 }
424 DE_TEST_ASSERT(!exists);
425 }
426
427 // Basic custom deleter.
428 {
429 bool exists = false;
430 bool deleterCalled = false;
431 {
432 SharedPtr<Object, CustomDeleter> ptr(new Object(exists), CustomDeleter(&deleterCalled));
433 DE_TEST_ASSERT(exists);
434 DE_TEST_ASSERT(!deleterCalled);
435 DE_TEST_ASSERT(ptr.get() != DE_NULL);
436 }
437 DE_TEST_ASSERT(!exists);
438 DE_TEST_ASSERT(deleterCalled);
439 }
440 }
441
442 } // de
443