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 32namespace de 33{ 34 35//! Shared pointer self-test. 36void SharedPtr_selfTest (void); 37 38class DeadReferenceException : public std::exception 39{ 40public: 41 DeadReferenceException (void) throw() : std::exception() {} 42 const char* what (void) const throw() { return "DeadReferenceException"; } 43}; 44 45template<bool threadSafe> 46struct ReferenceCount; 47 48template<> struct ReferenceCount<true> { typedef volatile int Type; }; 49template<> struct ReferenceCount<false> { typedef int Type; }; 50 51template<class Deleter, bool threadSafe> 52struct 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 66template<typename DstDeleterType, typename SrcDeleterType, bool threadSafe> 67SharedPtrState<DstDeleterType, threadSafe>* sharedPtrStateCast (SharedPtrState<SrcDeleterType, threadSafe>* state) 68{ 69 return reinterpret_cast<SharedPtrState<DstDeleterType, threadSafe>*>(state); 70} 71 72template<typename T, class Deleter, bool threadSafe> 73class SharedPtr; 74 75template<typename T, class Deleter, bool threadSafe> 76class 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 *//*--------------------------------------------------------------------*/ 97template<typename T, class Deleter = DefaultDeleter<T>, bool threadSafe = true> 98class SharedPtr 99{ 100public: 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 135private: 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 *//*--------------------------------------------------------------------*/ 163template<typename T, class Deleter = DefaultDeleter<T>, bool threadSafe = true> 164class WeakPtr 165{ 166public: 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 177private: 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 *//*--------------------------------------------------------------------*/ 192template<typename T, class Deleter, bool threadSafe> 193inline 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 *//*--------------------------------------------------------------------*/ 208template<typename T, class Deleter, bool threadSafe> 209template<typename Y> 210inline 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 *//*--------------------------------------------------------------------*/ 233template<typename T, class Deleter, bool threadSafe> 234inline 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 *//*--------------------------------------------------------------------*/ 247template<typename T, class Deleter, bool threadSafe> 248template<typename Y, class DeleterY> 249inline 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 *//*--------------------------------------------------------------------*/ 262template<typename T, class Deleter, bool threadSafe> 263template<typename Y, class DeleterY> 264inline 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 271template<typename T, class Deleter, bool threadSafe> 272inline 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 *//*--------------------------------------------------------------------*/ 287template<typename T, class Deleter, bool threadSafe> 288template<typename Y, class DeleterY> 289inline 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 *//*--------------------------------------------------------------------*/ 314template<typename T, class Deleter, bool threadSafe> 315inline 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 *//*--------------------------------------------------------------------*/ 345template<typename T, class Deleter, bool threadSafe> 346template<typename Y, class DeleterY> 347inline 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 *//*--------------------------------------------------------------------*/ 366template<class T, class Deleter, bool threadSafe> 367template<typename Y, class DeleterY> 368inline 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 *//*--------------------------------------------------------------------*/ 379template<class T, class DeleterT, bool threadSafeT, class U, class DeleterU, bool threadSafeU> 380inline 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 *//*--------------------------------------------------------------------*/ 391template<class T, class DeleterT, bool threadSafeT, class U, class DeleterU, bool threadSafeU> 392inline 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. */ 398template<typename T, class Deleter, bool threadSafe> 399inline 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. */ 407template<typename T, class Deleter, bool threadSafe> 408inline 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 *//*--------------------------------------------------------------------*/ 418template<typename T, class Deleter, bool threadSafe> 419inline void SharedPtr<T, Deleter, threadSafe>::clear (void) 420{ 421 release(); 422 m_ptr = DE_NULL; 423 m_state = DE_NULL; 424} 425 426template<typename T, class Deleter, bool threadSafe> 427inline 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 464template<typename T, class Deleter, bool threadSafe> 465inline 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 482template<typename T, class Deleter, bool threadSafe> 483inline 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 *//*--------------------------------------------------------------------*/ 527template<typename T, class Deleter, bool threadSafe> 528inline 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 *//*--------------------------------------------------------------------*/ 538template<typename T, class Deleter, bool threadSafe> 539inline 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 *//*--------------------------------------------------------------------*/ 550template<typename T, class Deleter, bool threadSafe> 551inline 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 558template<typename T, class Deleter, bool threadSafe> 559inline 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 *//*--------------------------------------------------------------------*/ 572template<typename T, class Deleter, bool threadSafe> 573inline 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 *//*--------------------------------------------------------------------*/ 596template<typename T, class Deleter, bool threadSafe> 597inline 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 609template<typename T, class Deleter, bool threadSafe> 610inline 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 621template<typename T, class Deleter, bool threadSafe> 622inline 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