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::__anon067914ac0111::CustomDeleter147 	CustomDeleter (bool* called) : m_called(called) {}
148 
operator ()de::__anon067914ac0111::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> 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