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