1 /* 2 * Copyright 2004 The WebRTC Project Authors. All rights reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 /* 12 * linked_ptr - simple reference linked pointer 13 * (like reference counting, just using a linked list of the references 14 * instead of their count.) 15 * 16 * The implementation stores three pointers for every linked_ptr, but 17 * does not allocate anything on the free store. 18 */ 19 20 #ifndef WEBRTC_BASE_LINKED_PTR_H__ 21 #define WEBRTC_BASE_LINKED_PTR_H__ 22 23 namespace rtc { 24 25 /* For ANSI-challenged compilers, you may want to #define 26 * NO_MEMBER_TEMPLATES, explicit or mutable */ 27 #define NO_MEMBER_TEMPLATES 28 29 template <class X> class linked_ptr 30 { 31 public: 32 33 #ifndef NO_MEMBER_TEMPLATES 34 # define TEMPLATE_FUNCTION template <class Y> 35 TEMPLATE_FUNCTION friend class linked_ptr<Y>; 36 #else 37 # define TEMPLATE_FUNCTION 38 typedef X Y; 39 #endif 40 41 typedef X element_type; 42 throw()43 explicit linked_ptr(X* p = 0) throw() 44 : itsPtr(p) {itsPrev = itsNext = this;} ~linked_ptr()45 ~linked_ptr() 46 {release();} throw()47 linked_ptr(const linked_ptr& r) throw() 48 {acquire(r);} 49 linked_ptr& operator=(const linked_ptr& r) 50 { 51 if (this != &r) { 52 release(); 53 acquire(r); 54 } 55 return *this; 56 } 57 58 #ifndef NO_MEMBER_TEMPLATES 59 template <class Y> friend class linked_ptr<Y>; linked_ptr(const linked_ptr<Y> & r)60 template <class Y> linked_ptr(const linked_ptr<Y>& r) throw() 61 {acquire(r);} 62 template <class Y> linked_ptr& operator=(const linked_ptr<Y>& r) 63 { 64 if (this != &r) { 65 release(); 66 acquire(r); 67 } 68 return *this; 69 } 70 #endif // NO_MEMBER_TEMPLATES 71 throw()72 X& operator*() const throw() {return *itsPtr;} 73 X* operator->() const throw() {return itsPtr;} get()74 X* get() const throw() {return itsPtr;} unique()75 bool unique() const throw() {return itsPrev ? itsPrev==this : true;} 76 77 private: 78 X* itsPtr; 79 mutable const linked_ptr* itsPrev; 80 mutable const linked_ptr* itsNext; 81 acquire(const linked_ptr & r)82 void acquire(const linked_ptr& r) throw() 83 { // insert this to the list 84 itsPtr = r.itsPtr; 85 itsNext = r.itsNext; 86 itsNext->itsPrev = this; 87 itsPrev = &r; 88 #ifndef mutable 89 r.itsNext = this; 90 #else // for ANSI-challenged compilers 91 (const_cast<linked_ptr<X>*>(&r))->itsNext = this; 92 #endif 93 } 94 95 #ifndef NO_MEMBER_TEMPLATES acquire(const linked_ptr<Y> & r)96 template <class Y> void acquire(const linked_ptr<Y>& r) throw() 97 { // insert this to the list 98 itsPtr = r.itsPtr; 99 itsNext = r.itsNext; 100 itsNext->itsPrev = this; 101 itsPrev = &r; 102 #ifndef mutable 103 r.itsNext = this; 104 #else // for ANSI-challenged compilers 105 (const_cast<linked_ptr<X>*>(&r))->itsNext = this; 106 #endif 107 } 108 #endif // NO_MEMBER_TEMPLATES 109 release()110 void release() 111 { // erase this from the list, delete if unique 112 if (unique()) delete itsPtr; 113 else { 114 itsPrev->itsNext = itsNext; 115 itsNext->itsPrev = itsPrev; 116 itsPrev = itsNext = 0; 117 } 118 itsPtr = 0; 119 } 120 }; 121 122 } // namespace rtc 123 124 #endif // WEBRTC_BASE_LINKED_PTR_H__ 125 126