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() 42 : std::exception() 43 { 44 } 45 46 const char* what (void) const throw() 47 { 48 return "DeadReferenceException"; 49 } 50}; 51 52struct SharedPtrStateBase 53{ 54 SharedPtrStateBase (void) 55 : strongRefCount (0) 56 , weakRefCount (0) 57 { 58 } 59 60 virtual ~SharedPtrStateBase (void) throw() {} 61 virtual void deletePtr (void) throw() = 0; 62 63 volatile deInt32 strongRefCount; 64 volatile deInt32 weakRefCount; //!< WeakPtr references + StrongPtr references. 65}; 66 67template<typename Type, typename Deleter> 68struct SharedPtrState : public SharedPtrStateBase 69{ 70 SharedPtrState (Type* ptr, Deleter deleter) 71 : m_ptr (ptr) 72 , m_deleter (deleter) 73 { 74 } 75 76 virtual ~SharedPtrState (void) throw() 77 { 78 DE_ASSERT(!m_ptr); 79 } 80 81 virtual void deletePtr (void) throw() 82 { 83 m_deleter(m_ptr); 84 m_ptr = DE_NULL; 85 } 86 87private: 88 Type* m_ptr; 89 Deleter m_deleter; 90}; 91 92template<typename T> 93class SharedPtr; 94 95template<typename T> 96class WeakPtr; 97 98/*--------------------------------------------------------------------*//*! 99 * \brief Shared pointer 100 * 101 * SharedPtr is smart pointer for managing shared ownership to a pointer. 102 * Multiple SharedPtrs can maintain ownership to the pointer and it is 103 * destructed when last SharedPtr is destroyed. 104 * 105 * SharedPtr can also be NULL. 106 *//*--------------------------------------------------------------------*/ 107template<typename T> 108class SharedPtr 109{ 110public: 111 SharedPtr (void); 112 SharedPtr (const SharedPtr<T>& other); 113 explicit SharedPtr (T* ptr); 114 115 template<typename Deleter> 116 SharedPtr (T* ptr, Deleter deleter); 117 118 template<typename Y> 119 explicit SharedPtr (const SharedPtr<Y>& other); 120 121 template<typename Y> 122 explicit SharedPtr (const WeakPtr<Y>& other); 123 124 ~SharedPtr (void); 125 126 template<typename Y> 127 SharedPtr& operator= (const SharedPtr<Y>& other); 128 SharedPtr& operator= (const SharedPtr<T>& other); 129 130 template<typename Y> 131 SharedPtr& operator= (const WeakPtr<Y>& other); 132 133 T* get (void) const throw() { return m_ptr; } //!< Get stored pointer. 134 T* operator-> (void) const throw() { return m_ptr; } //!< Get stored pointer. 135 T& operator* (void) const throw() { return *m_ptr; } //!< De-reference pointer. 136 137 operator bool (void) const throw() { return !!m_ptr; } 138 139 void swap (SharedPtr<T>& other); 140 141 void clear (void); 142 143 template<typename Y> 144 operator SharedPtr<Y> (void) const; 145 146private: 147 void acquire (void); 148 void acquireFromWeak (const WeakPtr<T>& other); 149 void release (void); 150 151 T* m_ptr; 152 SharedPtrStateBase* m_state; 153 154 friend class WeakPtr<T>; 155 156 template<typename U> 157 friend class SharedPtr; 158}; 159 160/*--------------------------------------------------------------------*//*! 161 * \brief Weak pointer 162 * 163 * WeakPtr manages weak references to objects owned by SharedPtr. Shared 164 * pointer can be converted to weak pointer and vice versa. Weak pointer 165 * differs from SharedPtr by not affecting the lifetime of the managed 166 * object. 167 * 168 * WeakPtr can be converted back to SharedPtr but that operation can fail 169 * if the object is no longer live. In such case DeadReferenceException 170 * will be thrown. 171 *//*--------------------------------------------------------------------*/ 172template<typename T> 173class WeakPtr 174{ 175public: 176 WeakPtr (void); 177 WeakPtr (const WeakPtr<T>& other); 178 179 explicit WeakPtr (const SharedPtr<T>& other); 180 ~WeakPtr (void); 181 182 WeakPtr& operator= (const WeakPtr<T>& other); 183 WeakPtr& operator= (const SharedPtr<T>& other); 184 185 SharedPtr<T> lock (void); 186 187private: 188 void acquire (void); 189 void release (void); 190 191 T* m_ptr; 192 SharedPtrStateBase* m_state; 193 194 friend class SharedPtr<T>; 195}; 196 197// SharedPtr template implementation. 198 199/*--------------------------------------------------------------------*//*! 200 * \brief Construct empty shared pointer. 201 *//*--------------------------------------------------------------------*/ 202template<typename T> 203inline SharedPtr<T>::SharedPtr (void) 204 : m_ptr (DE_NULL) 205 , m_state (DE_NULL) 206{ 207} 208 209/*--------------------------------------------------------------------*//*! 210 * \brief Construct shared pointer from pointer. 211 * \param ptr Pointer to be managed. 212 * 213 * Ownership of the pointer will be transferred to SharedPtr and future 214 * SharedPtr's initialized or assigned from this SharedPtr. 215 * 216 * If allocation of shared state fails. The "ptr" argument will not be 217 * released. 218 *//*--------------------------------------------------------------------*/ 219template<typename T> 220inline SharedPtr<T>::SharedPtr (T* ptr) 221 : m_ptr (DE_NULL) 222 , m_state (DE_NULL) 223{ 224 try 225 { 226 m_ptr = ptr; 227 m_state = new SharedPtrState<T, DefaultDeleter<T> >(ptr, DefaultDeleter<T>()); 228 m_state->strongRefCount = 1; 229 m_state->weakRefCount = 1; 230 } 231 catch (...) 232 { 233 // \note ptr is not released. 234 delete m_state; 235 throw; 236 } 237} 238 239/*--------------------------------------------------------------------*//*! 240 * \brief Construct shared pointer from pointer. 241 * \param ptr Pointer to be managed. 242 * 243 * Ownership of the pointer will be transferred to SharedPtr and future 244 * SharedPtr's initialized or assigned from this SharedPtr. 245 * 246 * Deleter must be callable type and deleter is called with the pointer 247 * argument when the reference count becomes 0. 248 * 249 * If allocation of shared state fails. The "ptr" argument will not be 250 * released. 251 * 252 * Calling deleter or calling destructor for deleter should never throw. 253 *//*--------------------------------------------------------------------*/ 254template<typename T> 255template<typename Deleter> 256inline SharedPtr<T>::SharedPtr (T* ptr, Deleter deleter) 257 : m_ptr (DE_NULL) 258 , m_state (DE_NULL) 259{ 260 try 261 { 262 m_ptr = ptr; 263 m_state = new SharedPtrState<T, Deleter>(ptr, deleter); 264 m_state->strongRefCount = 1; 265 m_state->weakRefCount = 1; 266 } 267 catch (...) 268 { 269 // \note ptr is not released. 270 delete m_state; 271 throw; 272 } 273} 274 275/*--------------------------------------------------------------------*//*! 276 * \brief Initialize shared pointer from another SharedPtr. 277 * \param other Pointer to be shared. 278 *//*--------------------------------------------------------------------*/ 279template<typename T> 280inline SharedPtr<T>::SharedPtr (const SharedPtr<T>& other) 281 : m_ptr (other.m_ptr) 282 , m_state (other.m_state) 283{ 284 acquire(); 285} 286 287/*--------------------------------------------------------------------*//*! 288 * \brief Initialize shared pointer from another SharedPtr. 289 * \param other Pointer to be shared. 290 * 291 * Y* must be convertible to T*. 292 *//*--------------------------------------------------------------------*/ 293template<typename T> 294template<typename Y> 295inline SharedPtr<T>::SharedPtr (const SharedPtr<Y>& other) 296 : m_ptr (other.m_ptr) 297 , m_state (other.m_state) 298{ 299 acquire(); 300} 301 302/*--------------------------------------------------------------------*//*! 303 * \brief Initialize shared pointer from weak reference. 304 * \param other Pointer to be shared. 305 * 306 * Y* must be convertible to T*. 307 *//*--------------------------------------------------------------------*/ 308template<typename T> 309template<typename Y> 310inline SharedPtr<T>::SharedPtr (const WeakPtr<Y>& other) 311 : m_ptr (DE_NULL) 312 , m_state (DE_NULL) 313{ 314 acquireFromWeak(other); 315} 316 317template<typename T> 318inline SharedPtr<T>::~SharedPtr (void) 319{ 320 release(); 321} 322 323/*--------------------------------------------------------------------*//*! 324 * \brief Assign from other shared pointer. 325 * \param other Pointer to be shared. 326 * \return Reference to this SharedPtr. 327 * 328 * Reference to current pointer is released and reference to new pointer is 329 * acquired. 330 * 331 * Y* must be convertible to T*. 332 *//*--------------------------------------------------------------------*/ 333template<typename T> 334template<typename Y> 335inline SharedPtr<T>& SharedPtr<T>::operator= (const SharedPtr<Y>& other) 336{ 337 if (m_state == other.m_state) 338 return *this; 339 340 // Release current reference. 341 release(); 342 343 // Copy from other and acquire reference. 344 m_ptr = other.m_ptr; 345 m_state = other.m_state; 346 347 acquire(); 348 349 return *this; 350} 351 352/*--------------------------------------------------------------------*//*! 353 * \brief Assign from other shared pointer. 354 * \param other Pointer to be shared. 355 * \return Reference to this SharedPtr. 356 * 357 * Reference to current pointer is released and reference to new pointer is 358 * acquired. 359 *//*--------------------------------------------------------------------*/ 360template<typename T> 361inline SharedPtr<T>& SharedPtr<T>::operator= (const SharedPtr<T>& other) 362{ 363 if (m_state == other.m_state) 364 return *this; 365 366 // Release current reference. 367 release(); 368 369 // Copy from other and acquire reference. 370 m_ptr = other.m_ptr; 371 m_state = other.m_state; 372 373 acquire(); 374 375 return *this; 376} 377 378/*--------------------------------------------------------------------*//*! 379 * \brief Assign from weak pointer. 380 * \param other Weak reference. 381 * \return Reference to this SharedPtr. 382 * 383 * Tries to acquire reference to WeakPtr, releases current reference and 384 * holds reference to new pointer. 385 * 386 * If WeakPtr can't be acquired, throws DeadReferenceException and doesn't 387 * release the current reference. 388 * 389 * If WeakPtr references same pointer as SharedPtr this call will always 390 * succeed. 391 * 392 * Y* must be convertible to T*. 393 *//*--------------------------------------------------------------------*/ 394template<typename T> 395template<typename Y> 396inline SharedPtr<T>& SharedPtr<T>::operator= (const WeakPtr<Y>& other) 397{ 398 if (m_state == other.m_state) 399 return *this; 400 401 { 402 SharedPtr<T> sharedOther(other); 403 *this = other; 404 } 405 406 return *this; 407} 408 409/*--------------------------------------------------------------------*//*! 410 * \brief Type conversion operator. 411 * 412 * T* must be convertible to Y*. 413 *//*--------------------------------------------------------------------*/ 414template<class T> 415template<typename Y> 416inline SharedPtr<T>::operator SharedPtr<Y> (void) const 417{ 418 return SharedPtr<Y>(*this); 419} 420 421/*--------------------------------------------------------------------*//*! 422 * \brief Compare pointers. 423 * \param a A 424 * \param b B 425 * \return true if A and B point to same object, false otherwise. 426 *//*--------------------------------------------------------------------*/ 427template<class T, class U> 428inline bool operator== (const SharedPtr<T>& a, const SharedPtr<U>& b) throw() 429{ 430 return a.get() == b.get(); 431} 432 433/*--------------------------------------------------------------------*//*! 434 * \brief Compare pointers. 435 * \param a A 436 * \param b B 437 * \return true if A and B point to different objects, false otherwise. 438 *//*--------------------------------------------------------------------*/ 439template<class T, class U> 440inline bool operator!= (const SharedPtr<T>& a, const SharedPtr<U>& b) throw() 441{ 442 return a.get() != b.get(); 443} 444 445/** Swap pointer contents. */ 446template<typename T> 447inline void SharedPtr<T>::swap (SharedPtr<T>& other) 448{ 449 using std::swap; 450 swap(m_ptr, other.m_ptr); 451 swap(m_state, other.m_state); 452} 453 454/** Swap operator for SharedPtr's. */ 455template<typename T> 456inline void swap (SharedPtr<T>& a, SharedPtr<T>& b) 457{ 458 a.swap(b); 459} 460 461/*--------------------------------------------------------------------*//*! 462 * \brief Set pointer to null. 463 * 464 * clear() removes current reference and sets pointer to null value. 465 *//*--------------------------------------------------------------------*/ 466template<typename T> 467inline void SharedPtr<T>::clear (void) 468{ 469 release(); 470 m_ptr = DE_NULL; 471 m_state = DE_NULL; 472} 473 474template<typename T> 475inline void SharedPtr<T>::acquireFromWeak (const WeakPtr<T>& weakRef) 476{ 477 DE_ASSERT(!m_ptr && !m_state); 478 479 SharedPtrStateBase* state = weakRef.m_state; 480 481 if (!state) 482 return; // Empty reference. 483 484 { 485 deInt32 oldCount, newCount; 486 487 // Do atomic compare and increment. 488 do 489 { 490 oldCount = state->strongRefCount; 491 if (oldCount == 0) 492 throw DeadReferenceException(); 493 newCount = oldCount+1; 494 } while (deAtomicCompareExchange32((deUint32 volatile*)&state->strongRefCount, (deUint32)oldCount, (deUint32)newCount) != (deUint32)oldCount); 495 496 deAtomicIncrement32(&state->weakRefCount); 497 } 498 499 m_ptr = weakRef.m_ptr; 500 m_state = state; 501} 502 503template<typename T> 504inline void SharedPtr<T>::acquire (void) 505{ 506 if (m_state) 507 { 508 deAtomicIncrement32(&m_state->strongRefCount); 509 deAtomicIncrement32(&m_state->weakRefCount); 510 } 511} 512 513template<typename T> 514inline void SharedPtr<T>::release (void) 515{ 516 if (m_state) 517 { 518 if (deAtomicDecrement32(&m_state->strongRefCount) == 0) 519 { 520 m_ptr = DE_NULL; 521 m_state->deletePtr(); 522 } 523 524 if (deAtomicDecrement32(&m_state->weakRefCount) == 0) 525 { 526 delete m_state; 527 m_state = DE_NULL; 528 } 529 } 530} 531 532// WeakPtr template implementation. 533 534/*--------------------------------------------------------------------*//*! 535 * \brief Construct empty weak pointer. 536 *//*--------------------------------------------------------------------*/ 537template<typename T> 538inline WeakPtr<T>::WeakPtr (void) 539 : m_ptr (DE_NULL) 540 , m_state (DE_NULL) 541{ 542} 543 544/*--------------------------------------------------------------------*//*! 545 * \brief Construct weak pointer from other weak reference. 546 * \param other Weak reference. 547 *//*--------------------------------------------------------------------*/ 548template<typename T> 549inline WeakPtr<T>::WeakPtr (const WeakPtr<T>& other) 550 : m_ptr (other.m_ptr) 551 , m_state (other.m_state) 552{ 553 acquire(); 554} 555 556/*--------------------------------------------------------------------*//*! 557 * \brief Construct weak pointer from shared pointer. 558 * \param other Shared pointer. 559 *//*--------------------------------------------------------------------*/ 560template<typename T> 561inline WeakPtr<T>::WeakPtr (const SharedPtr<T>& other) 562 : m_ptr (other.m_ptr) 563 , m_state (other.m_state) 564{ 565 acquire(); 566} 567 568template<typename T> 569inline WeakPtr<T>::~WeakPtr (void) 570{ 571 release(); 572} 573 574/*--------------------------------------------------------------------*//*! 575 * \brief Assign from another weak pointer. 576 * \param other Weak reference. 577 * \return Reference to this WeakPtr. 578 * 579 * The current weak reference is removed first and then a new weak reference 580 * to the object pointed by other is taken. 581 *//*--------------------------------------------------------------------*/ 582template<typename T> 583inline WeakPtr<T>& WeakPtr<T>::operator= (const WeakPtr<T>& other) 584{ 585 if (this == &other) 586 return *this; 587 588 release(); 589 590 m_ptr = other.m_ptr; 591 m_state = other.m_state; 592 593 acquire(); 594 595 return *this; 596} 597 598/*--------------------------------------------------------------------*//*! 599 * \brief Assign from shared pointer. 600 * \param other Shared pointer. 601 * \return Reference to this WeakPtr. 602 * 603 * The current weak reference is removed first and then a new weak reference 604 * to the object pointed by other is taken. 605 *//*--------------------------------------------------------------------*/ 606template<typename T> 607inline WeakPtr<T>& WeakPtr<T>::operator= (const SharedPtr<T>& other) 608{ 609 release(); 610 611 m_ptr = other.m_ptr; 612 m_state = other.m_state; 613 614 acquire(); 615 616 return *this; 617} 618 619template<typename T> 620inline void WeakPtr<T>::acquire (void) 621{ 622 if (m_state) 623 deAtomicIncrement32(&m_state->weakRefCount); 624} 625 626template<typename T> 627inline void WeakPtr<T>::release (void) 628{ 629 if (m_state) 630 { 631 if (deAtomicDecrement32(&m_state->weakRefCount) == 0) 632 { 633 delete m_state; 634 m_state = DE_NULL; 635 m_ptr = DE_NULL; 636 } 637 } 638} 639 640} // de 641 642#endif // _DESHAREDPTR_HPP 643