Home | History | Annotate | Download | only in decpp
      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:
     44 	Object (bool& exists)
     45 		: m_exists(exists)
     46 	{
     47 		m_exists = true;
     48 	}
     49 
     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:
     62 	DerivedObject (bool& exists)
     63 		: Object(exists)
     64 	{
     65 	}
     66 };
     67 
     68 class SharedPtrTestThread : public Thread
     69 {
     70 public:
     71 	SharedPtrTestThread (const SharedPtr<Object>& ptr, const bool& exists)
     72 		: m_ptr		(ptr)
     73 		, m_exists	(exists)
     74 	{
     75 	}
     76 
     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:
    107 	WeakPtrTestThread (const SharedPtr<Object>& ptr, const bool& exists)
    108 		: m_ptr		(ptr)
    109 		, m_exists	(exists)
    110 	{
    111 	}
    112 
    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 
    140 SharedPtr<Object> makeObject (bool& exists)
    141 {
    142 	return SharedPtr<Object>(new Object(exists));
    143 }
    144 
    145 struct CustomDeleter
    146 {
    147 	CustomDeleter (bool* called) : m_called(called) {}
    148 
    149 	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 
    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