1 #ifndef _DESHAREDPTR_HPP 2 #define _DESHAREDPTR_HPP 3 /*------------------------------------------------------------------------- 4 * drawElements C++ Base Library 5 * ----------------------------- 6 * 7 * Copyright 2014 The Android Open Source Project 8 * 9 * Licensed under the Apache License, Version 2.0 (the "License"); 10 * you may not use this file except in compliance with the License. 11 * You may obtain a copy of the License at 12 * 13 * http://www.apache.org/licenses/LICENSE-2.0 14 * 15 * Unless required by applicable law or agreed to in writing, software 16 * distributed under the License is distributed on an "AS IS" BASIS, 17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 * See the License for the specific language governing permissions and 19 * limitations under the License. 20 * 21 *//*! 22 * \file 23 * \brief Shared pointer. 24 *//*--------------------------------------------------------------------*/ 25 26 #include "deDefs.hpp" 27 #include "deAtomic.h" 28 29 #include <exception> 30 #include <algorithm> 31 32 namespace de 33 { 34 35 //! Shared pointer self-test. 36 void SharedPtr_selfTest (void); 37 38 class DeadReferenceException : public std::exception 39 { 40 public: 41 DeadReferenceException (void) throw() : std::exception() {} 42 const char* what (void) const throw() { return "DeadReferenceException"; } 43 }; 44 45 template<bool threadSafe> 46 struct ReferenceCount; 47 48 template<> struct ReferenceCount<true> { typedef volatile int Type; }; 49 template<> struct ReferenceCount<false> { typedef int Type; }; 50 51 template<class Deleter, bool threadSafe> 52 struct SharedPtrState 53 { 54 SharedPtrState (Deleter deleter_) 55 : strongRefCount (0) 56 , weakRefCount (0) 57 , deleter (deleter_) 58 { 59 } 60 61 typename ReferenceCount<threadSafe>::Type strongRefCount; 62 typename ReferenceCount<threadSafe>::Type weakRefCount; //!< WeakPtr references + StrongPtr references. 63 Deleter deleter; 64 }; 65 66 template<typename DstDeleterType, typename SrcDeleterType, bool threadSafe> 67 SharedPtrState<DstDeleterType, threadSafe>* sharedPtrStateCast (SharedPtrState<SrcDeleterType, threadSafe>* state) 68 { 69 return reinterpret_cast<SharedPtrState<DstDeleterType, threadSafe>*>(state); 70 } 71 72 template<typename T, class Deleter, bool threadSafe> 73 class SharedPtr; 74 75 template<typename T, class Deleter, bool threadSafe> 76 class WeakPtr; 77 78 /*--------------------------------------------------------------------*//*! 79 * \brief Shared pointer 80 * 81 * SharedPtr is smart pointer for managing shared ownership to a pointer. 82 * Multiple SharedPtr's can maintain ownership to the pointer and it is 83 * destructed when last SharedPtr is destroyed. 84 * 85 * Shared pointers can be assigned (or initialized using copy constructor) 86 * and in such case the previous reference is first freed and then a new 87 * reference to the new pointer is acquired. 88 * 89 * SharedPtr can also be empty. 90 * 91 * If threadSafe template parameter is set to true, it is safe to share 92 * data using SharedPtr across threads. SharedPtr object itself is not 93 * thread safe and should not be mutated from multiple threads simultaneously. 94 * 95 * \todo [2012-10-26 pyry] Add custom deleter. 96 *//*--------------------------------------------------------------------*/ 97 template<typename T, class Deleter = DefaultDeleter<T>, bool threadSafe = true> 98 class SharedPtr 99 { 100 public: 101 SharedPtr (void); 102 SharedPtr (const SharedPtr<T, Deleter, threadSafe>& other); 103 104 template<typename Y> 105 explicit SharedPtr (Y* ptr, Deleter deleter = Deleter()); 106 107 template<typename Y, class DeleterY> 108 explicit SharedPtr (const SharedPtr<Y, DeleterY, threadSafe>& other); 109 110 template<typename Y, class DeleterY> 111 explicit SharedPtr (const WeakPtr<Y, DeleterY, threadSafe>& other); 112 113 ~SharedPtr (void); 114 115 template<typename Y, class DeleterY> 116 SharedPtr& operator= (const SharedPtr<Y, DeleterY, threadSafe>& other); 117 SharedPtr& operator= (const SharedPtr<T, Deleter, threadSafe>& other); 118 119 template<typename Y, class DeleterY> 120 SharedPtr& operator= (const WeakPtr<Y, DeleterY, threadSafe>& other); 121 122 T* get (void) const throw() { return m_ptr; } //!< Get stored pointer. 123 T* operator-> (void) const throw() { return m_ptr; } //!< Get stored pointer. 124 T& operator* (void) const throw() { return *m_ptr; } //!< De-reference pointer. 125 126 operator bool (void) const throw() { return !!m_ptr; } 127 128 void swap (SharedPtr<T, Deleter, threadSafe>& other); 129 130 void clear (void); 131 132 template<typename Y, class DeleterY> 133 operator SharedPtr<Y, DeleterY, threadSafe> (void) const; 134 135 private: 136 void acquire (void); 137 void acquireFromWeak (const WeakPtr<T, Deleter, threadSafe>& other); 138 void release (void); 139 140 T* m_ptr; 141 SharedPtrState<Deleter, threadSafe>* m_state; 142 143 friend class WeakPtr<T, Deleter, threadSafe>; 144 145 template<typename U, class DeleterU, bool threadSafeU> 146 friend class SharedPtr; 147 }; 148 149 /*--------------------------------------------------------------------*//*! 150 * \brief Weak pointer 151 * 152 * WeakPtr manages weak references to objects owned by SharedPtr. Shared 153 * pointer can be converted to weak pointer and vice versa. Weak pointer 154 * differs from SharedPtr by not affecting the lifetime of the managed 155 * object. 156 * 157 * WeakPtr can be converted back to SharedPtr but that operation can fail 158 * if the object is no longer live. In such case DeadReferenceException 159 * will be thrown. 160 * 161 * \todo [2012-10-26 pyry] Add custom deleter. 162 *//*--------------------------------------------------------------------*/ 163 template<typename T, class Deleter = DefaultDeleter<T>, bool threadSafe = true> 164 class WeakPtr 165 { 166 public: 167 WeakPtr (void); 168 WeakPtr (const WeakPtr<T, Deleter, threadSafe>& other); 169 explicit WeakPtr (const SharedPtr<T, Deleter, threadSafe>& other); 170 ~WeakPtr (void); 171 172 WeakPtr& operator= (const WeakPtr<T, Deleter, threadSafe>& other); 173 WeakPtr& operator= (const SharedPtr<T, Deleter, threadSafe>& other); 174 175 SharedPtr<T, Deleter, threadSafe> lock (void); 176 177 private: 178 void acquire (void); 179 void release (void); 180 181 T* m_ptr; 182 SharedPtrState<Deleter, threadSafe>* m_state; 183 184 friend class SharedPtr<T, Deleter, threadSafe>; 185 }; 186 187 // SharedPtr template implementation. 188 189 /*--------------------------------------------------------------------*//*! 190 * \brief Construct empty shared pointer. 191 *//*--------------------------------------------------------------------*/ 192 template<typename T, class Deleter, bool threadSafe> 193 inline SharedPtr<T, Deleter, threadSafe>::SharedPtr (void) 194 : m_ptr (DE_NULL) 195 , m_state (DE_NULL) 196 { 197 } 198 199 /*--------------------------------------------------------------------*//*! 200 * \brief Construct shared pointer from pointer. 201 * \param ptr Pointer to be managed. 202 * 203 * Ownership of the pointer will be transferred to SharedPtr and future 204 * SharedPtr's initialized or assigned from this SharedPtr. 205 * 206 * Y* must be convertible to T*. 207 *//*--------------------------------------------------------------------*/ 208 template<typename T, class Deleter, bool threadSafe> 209 template<typename Y> 210 inline SharedPtr<T, Deleter, threadSafe>::SharedPtr (Y* ptr, Deleter deleter) 211 : m_ptr (DE_NULL) 212 , m_state (DE_NULL) 213 { 214 try 215 { 216 m_ptr = ptr; 217 m_state = new SharedPtrState<Deleter, threadSafe>(deleter); 218 m_state->strongRefCount = 1; 219 m_state->weakRefCount = 1; 220 } 221 catch (...) 222 { 223 delete m_ptr; 224 delete m_state; 225 throw; 226 } 227 } 228 229 /*--------------------------------------------------------------------*//*! 230 * \brief Initialize shared pointer from another SharedPtr. 231 * \param other Pointer to be shared. 232 *//*--------------------------------------------------------------------*/ 233 template<typename T, class Deleter, bool threadSafe> 234 inline SharedPtr<T, Deleter, threadSafe>::SharedPtr (const SharedPtr<T, Deleter, threadSafe>& other) 235 : m_ptr (other.m_ptr) 236 , m_state (other.m_state) 237 { 238 acquire(); 239 } 240 241 /*--------------------------------------------------------------------*//*! 242 * \brief Initialize shared pointer from another SharedPtr. 243 * \param other Pointer to be shared. 244 * 245 * Y* must be convertible to T*. 246 *//*--------------------------------------------------------------------*/ 247 template<typename T, class Deleter, bool threadSafe> 248 template<typename Y, class DeleterY> 249 inline SharedPtr<T, Deleter, threadSafe>::SharedPtr (const SharedPtr<Y, DeleterY, threadSafe>& other) 250 : m_ptr (other.m_ptr) 251 , m_state (sharedPtrStateCast<Deleter>(other.m_state)) 252 { 253 acquire(); 254 } 255 256 /*--------------------------------------------------------------------*//*! 257 * \brief Initialize shared pointer from weak reference. 258 * \param other Pointer to be shared. 259 * 260 * Y* must be convertible to T*. 261 *//*--------------------------------------------------------------------*/ 262 template<typename T, class Deleter, bool threadSafe> 263 template<typename Y, class DeleterY> 264 inline SharedPtr<T, Deleter, threadSafe>::SharedPtr (const WeakPtr<Y, DeleterY, threadSafe>& other) 265 : m_ptr (DE_NULL) 266 , m_state (DE_NULL) 267 { 268 acquireFromWeak(other); 269 } 270 271 template<typename T, class Deleter, bool threadSafe> 272 inline SharedPtr<T, Deleter, threadSafe>::~SharedPtr (void) 273 { 274 release(); 275 } 276 277 /*--------------------------------------------------------------------*//*! 278 * \brief Assign from other shared pointer. 279 * \param other Pointer to be shared. 280 * \return Reference to this SharedPtr. 281 * 282 * Reference to current pointer (if any) will be released first. Then a new 283 * reference to the pointer managed by other will be acquired. 284 * 285 * Y* must be convertible to T*. 286 *//*--------------------------------------------------------------------*/ 287 template<typename T, class Deleter, bool threadSafe> 288 template<typename Y, class DeleterY> 289 inline SharedPtr<T, Deleter, threadSafe>& SharedPtr<T, Deleter, threadSafe>::operator= (const SharedPtr<Y, DeleterY, threadSafe>& other) 290 { 291 if (*this == other) 292 return *this; 293 294 // Release current reference. 295 release(); 296 297 // Copy from other and acquire reference. 298 m_ptr = other.m_ptr; 299 m_state = sharedPtrStateCast<Deleter>(other.m_state); 300 301 acquire(); 302 303 return *this; 304 } 305 306 /*--------------------------------------------------------------------*//*! 307 * \brief Assign from other shared pointer. 308 * \param other Pointer to be shared. 309 * \return Reference to this SharedPtr. 310 * 311 * Reference to current pointer (if any) will be released first. Then a new 312 * reference to the pointer managed by other will be acquired. 313 *//*--------------------------------------------------------------------*/ 314 template<typename T, class Deleter, bool threadSafe> 315 inline SharedPtr<T, Deleter, threadSafe>& SharedPtr<T, Deleter, threadSafe>::operator= (const SharedPtr<T, Deleter, threadSafe>& other) 316 { 317 if (*this == other) 318 return *this; 319 320 // Release current reference. 321 release(); 322 323 // Copy from other and acquire reference. 324 m_ptr = other.m_ptr; 325 m_state = other.m_state; 326 327 acquire(); 328 329 return *this; 330 } 331 332 /*--------------------------------------------------------------------*//*! 333 * \brief Assign from weak pointer. 334 * \param other Weak reference. 335 * \return Reference to this SharedPtr. 336 * 337 * Reference to current pointer (if any) will be released first. Then a 338 * reference to pointer managed by WeakPtr is acquired if the pointer 339 * is still live (eg. there's at least one strong reference). 340 * 341 * If pointer is no longer live, DeadReferenceException is thrown. 342 * 343 * Y* must be convertible to T*. 344 *//*--------------------------------------------------------------------*/ 345 template<typename T, class Deleter, bool threadSafe> 346 template<typename Y, class DeleterY> 347 inline SharedPtr<T, Deleter, threadSafe>& SharedPtr<T, Deleter, threadSafe>::operator= (const WeakPtr<Y, DeleterY, threadSafe>& other) 348 { 349 // Release current reference. 350 release(); 351 352 m_ptr = DE_NULL; 353 m_state = DE_NULL; 354 355 acquireFromWeak(other); 356 357 return *this; 358 } 359 360 /*--------------------------------------------------------------------*//*! 361 * \brief Type conversion operator. 362 * 363 * T* must be convertible to Y*. Since resulting SharedPtr will share the 364 * ownership destroying Y* must be equal to destroying T*. 365 *//*--------------------------------------------------------------------*/ 366 template<class T, class Deleter, bool threadSafe> 367 template<typename Y, class DeleterY> 368 inline SharedPtr<T, Deleter, threadSafe>::operator SharedPtr<Y, DeleterY, threadSafe> (void) const 369 { 370 return SharedPtr<Y, DeleterY, threadSafe>(*this); 371 } 372 373 /*--------------------------------------------------------------------*//*! 374 * \brief Compare pointers. 375 * \param a A 376 * \param b B 377 * \return true if A and B point to same object, false otherwise. 378 *//*--------------------------------------------------------------------*/ 379 template<class T, class DeleterT, bool threadSafeT, class U, class DeleterU, bool threadSafeU> 380 inline bool operator== (const SharedPtr<T, DeleterT, threadSafeT>& a, const SharedPtr<U, DeleterU, threadSafeU>& b) throw() 381 { 382 return a.get() == b.get(); 383 } 384 385 /*--------------------------------------------------------------------*//*! 386 * \brief Compare pointers. 387 * \param a A 388 * \param b B 389 * \return true if A and B point to different objects, false otherwise. 390 *//*--------------------------------------------------------------------*/ 391 template<class T, class DeleterT, bool threadSafeT, class U, class DeleterU, bool threadSafeU> 392 inline bool operator!= (const SharedPtr<T, DeleterT, threadSafeT>& a, const SharedPtr<U, DeleterU, threadSafeU>& b) throw() 393 { 394 return a.get() != b.get(); 395 } 396 397 /** Swap pointer contents. */ 398 template<typename T, class Deleter, bool threadSafe> 399 inline void SharedPtr<T, Deleter, threadSafe>::swap (SharedPtr<T, Deleter, threadSafe>& other) 400 { 401 using std::swap; 402 swap(m_ptr, other.m_ptr); 403 swap(m_state, other.m_state); 404 } 405 406 /** Swap operator for SharedPtr's. */ 407 template<typename T, class Deleter, bool threadSafe> 408 inline void swap (SharedPtr<T, Deleter, threadSafe>& a, SharedPtr<T, Deleter, threadSafe>& b) 409 { 410 a.swap(b); 411 } 412 413 /*--------------------------------------------------------------------*//*! 414 * \brief Set pointer to null. 415 * 416 * clear() removes current reference and sets pointer to null value. 417 *//*--------------------------------------------------------------------*/ 418 template<typename T, class Deleter, bool threadSafe> 419 inline void SharedPtr<T, Deleter, threadSafe>::clear (void) 420 { 421 release(); 422 m_ptr = DE_NULL; 423 m_state = DE_NULL; 424 } 425 426 template<typename T, class Deleter, bool threadSafe> 427 inline void SharedPtr<T, Deleter, threadSafe>::acquireFromWeak (const WeakPtr<T, Deleter, threadSafe>& weakRef) 428 { 429 DE_ASSERT(!m_ptr && !m_state); 430 431 SharedPtrState<Deleter, threadSafe>* state = weakRef.m_state; 432 433 if (!state) 434 return; // Empty reference. 435 436 if (threadSafe) 437 { 438 int oldCount, newCount; 439 440 // Do atomic compare and increment. 441 do 442 { 443 oldCount = state->strongRefCount; 444 if (oldCount == 0) 445 throw DeadReferenceException(); 446 newCount = oldCount+1; 447 } while (deAtomicCompareExchange32((deUint32 volatile*)&state->strongRefCount, (deUint32)oldCount, (deUint32)newCount) != (deUint32)oldCount); 448 449 deAtomicIncrement32(&state->weakRefCount); 450 } 451 else 452 { 453 if (state->strongRefCount == 0) 454 throw DeadReferenceException(); 455 456 state->strongRefCount += 1; 457 state->weakRefCount += 1; 458 } 459 460 m_ptr = weakRef.m_ptr; 461 m_state = state; 462 } 463 464 template<typename T, class Deleter, bool threadSafe> 465 inline void SharedPtr<T, Deleter, threadSafe>::acquire (void) 466 { 467 if (m_state) 468 { 469 if (threadSafe) 470 { 471 deAtomicIncrement32((deInt32 volatile*)&m_state->strongRefCount); 472 deAtomicIncrement32((deInt32 volatile*)&m_state->weakRefCount); 473 } 474 else 475 { 476 m_state->strongRefCount += 1; 477 m_state->weakRefCount += 1; 478 } 479 } 480 } 481 482 template<typename T, class Deleter, bool threadSafe> 483 inline void SharedPtr<T, Deleter, threadSafe>::release (void) 484 { 485 if (m_state) 486 { 487 if (threadSafe) 488 { 489 if (deAtomicDecrement32(&m_state->strongRefCount) == 0) 490 { 491 m_state->deleter(m_ptr); 492 m_ptr = DE_NULL; 493 } 494 495 if (deAtomicDecrement32(&m_state->weakRefCount) == 0) 496 { 497 delete m_state; 498 m_state = DE_NULL; 499 } 500 } 501 else 502 { 503 m_state->strongRefCount -= 1; 504 m_state->weakRefCount -= 1; 505 DE_ASSERT(m_state->strongRefCount >= 0 && m_state->weakRefCount >= 0); 506 507 if (m_state->strongRefCount == 0) 508 { 509 m_state->deleter(m_ptr); 510 m_ptr = DE_NULL; 511 } 512 513 if (m_state->weakRefCount == 0) 514 { 515 delete m_state; 516 m_state = DE_NULL; 517 } 518 } 519 } 520 } 521 522 // WeakPtr template implementation. 523 524 /*--------------------------------------------------------------------*//*! 525 * \brief Construct empty weak pointer. 526 *//*--------------------------------------------------------------------*/ 527 template<typename T, class Deleter, bool threadSafe> 528 inline WeakPtr<T, Deleter, threadSafe>::WeakPtr (void) 529 : m_ptr (DE_NULL) 530 , m_state (DE_NULL) 531 { 532 } 533 534 /*--------------------------------------------------------------------*//*! 535 * \brief Construct weak pointer from other weak reference. 536 * \param other Weak reference. 537 *//*--------------------------------------------------------------------*/ 538 template<typename T, class Deleter, bool threadSafe> 539 inline WeakPtr<T, Deleter, threadSafe>::WeakPtr (const WeakPtr<T, Deleter, threadSafe>& other) 540 : m_ptr (other.m_ptr) 541 , m_state (other.m_state) 542 { 543 acquire(); 544 } 545 546 /*--------------------------------------------------------------------*//*! 547 * \brief Construct weak pointer from shared pointer. 548 * \param other Shared pointer. 549 *//*--------------------------------------------------------------------*/ 550 template<typename T, class Deleter, bool threadSafe> 551 inline WeakPtr<T, Deleter, threadSafe>::WeakPtr (const SharedPtr<T, Deleter, threadSafe>& other) 552 : m_ptr (other.m_ptr) 553 , m_state (other.m_state) 554 { 555 acquire(); 556 } 557 558 template<typename T, class Deleter, bool threadSafe> 559 inline WeakPtr<T, Deleter, threadSafe>::~WeakPtr (void) 560 { 561 release(); 562 } 563 564 /*--------------------------------------------------------------------*//*! 565 * \brief Assign from another weak pointer. 566 * \param other Weak reference. 567 * \return Reference to this WeakPtr. 568 * 569 * The current weak reference is removed first and then a new weak reference 570 * to the object pointed by other is taken. 571 *//*--------------------------------------------------------------------*/ 572 template<typename T, class Deleter, bool threadSafe> 573 inline WeakPtr<T, Deleter, threadSafe>& WeakPtr<T, Deleter, threadSafe>::operator= (const WeakPtr<T, Deleter, threadSafe>& other) 574 { 575 if (this == &other) 576 return *this; 577 578 release(); 579 580 m_ptr = other.m_ptr; 581 m_state = other.m_state; 582 583 acquire(); 584 585 return *this; 586 } 587 588 /*--------------------------------------------------------------------*//*! 589 * \brief Assign from shared pointer. 590 * \param other Shared pointer. 591 * \return Reference to this WeakPtr. 592 * 593 * The current weak reference is removed first and then a new weak reference 594 * to the object pointed by other is taken. 595 *//*--------------------------------------------------------------------*/ 596 template<typename T, class Deleter, bool threadSafe> 597 inline WeakPtr<T, Deleter, threadSafe>& WeakPtr<T, Deleter, threadSafe>::operator= (const SharedPtr<T, Deleter, threadSafe>& other) 598 { 599 release(); 600 601 m_ptr = other.m_ptr; 602 m_state = other.m_state; 603 604 acquire(); 605 606 return *this; 607 } 608 609 template<typename T, class Deleter, bool threadSafe> 610 inline void WeakPtr<T, Deleter, threadSafe>::acquire (void) 611 { 612 if (m_state) 613 { 614 if (threadSafe) 615 deAtomicIncrement32(&m_state->weakRefCount); 616 else 617 m_state->weakRefCount += 1; 618 } 619 } 620 621 template<typename T, class Deleter, bool threadSafe> 622 inline void WeakPtr<T, Deleter, threadSafe>::release (void) 623 { 624 if (m_state) 625 { 626 if (threadSafe) 627 { 628 if (deAtomicDecrement32(&m_state->weakRefCount) == 0) 629 { 630 delete m_state; 631 m_state = DE_NULL; 632 m_ptr = DE_NULL; 633 } 634 } 635 else 636 { 637 m_state->weakRefCount -= 1; 638 DE_ASSERT(m_state->weakRefCount >= 0); 639 640 if (m_state->weakRefCount == 0) 641 { 642 delete m_state; 643 m_state = DE_NULL; 644 m_ptr = DE_NULL; 645 } 646 } 647 } 648 } 649 650 } // de 651 652 #endif // _DESHAREDPTR_HPP 653