diff options
Diffstat (limited to 'Plugins/jingle/libjingle/talk/base/linked_ptr.h')
-rw-r--r-- | Plugins/jingle/libjingle/talk/base/linked_ptr.h | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/Plugins/jingle/libjingle/talk/base/linked_ptr.h b/Plugins/jingle/libjingle/talk/base/linked_ptr.h new file mode 100644 index 0000000..8d5ce49 --- /dev/null +++ b/Plugins/jingle/libjingle/talk/base/linked_ptr.h @@ -0,0 +1,115 @@ +/* + * linked_ptr - simple reference linked pointer + * (like reference counting, just using a linked list of the references + * instead of their count.) + * + * The implementation stores three pointers for every linked_ptr, but + * does not allocate anything on the free store. + */ + +#ifndef TALK_BASE_LINKED_PTR_H__ +#define TALK_BASE_LINKED_PTR_H__ + +namespace talk_base { + +/* For ANSI-challenged compilers, you may want to #define + * NO_MEMBER_TEMPLATES, explicit or mutable */ +#define NO_MEMBER_TEMPLATES + +template <class X> class linked_ptr +{ +public: + +#ifndef NO_MEMBER_TEMPLATES +# define TEMPLATE_FUNCTION template <class Y> + TEMPLATE_FUNCTION friend class linked_ptr<Y>; +#else +# define TEMPLATE_FUNCTION + typedef X Y; +#endif + + typedef X element_type; + + explicit linked_ptr(X* p = 0) throw() + : itsPtr(p) {itsPrev = itsNext = this;} + ~linked_ptr() + {release();} + linked_ptr(const linked_ptr& r) throw() + {acquire(r);} + linked_ptr& operator=(const linked_ptr& r) + { + if (this != &r) { + release(); + acquire(r); + } + return *this; + } + +#ifndef NO_MEMBER_TEMPLATES + template <class Y> friend class linked_ptr<Y>; + template <class Y> linked_ptr(const linked_ptr<Y>& r) throw() + {acquire(r);} + template <class Y> linked_ptr& operator=(const linked_ptr<Y>& r) + { + if (this != &r) { + release(); + acquire(r); + } + return *this; + } +#endif // NO_MEMBER_TEMPLATES + + X& operator*() const throw() {return *itsPtr;} + X* operator->() const throw() {return itsPtr;} + X* get() const throw() {return itsPtr;} + bool unique() const throw() {return itsPrev ? itsPrev==this : true;} + +private: + X* itsPtr; + mutable const linked_ptr* itsPrev; + mutable const linked_ptr* itsNext; + + void acquire(const linked_ptr& r) throw() + { // insert this to the list + itsPtr = r.itsPtr; + itsNext = r.itsNext; + itsNext->itsPrev = this; + itsPrev = &r; +#ifndef mutable + r.itsNext = this; +#else // for ANSI-challenged compilers + (const_cast<linked_ptr<X>*>(&r))->itsNext = this; +#endif + } + +#ifndef NO_MEMBER_TEMPLATES + template <class Y> void acquire(const linked_ptr<Y>& r) throw() + { // insert this to the list + itsPtr = r.itsPtr; + itsNext = r.itsNext; + itsNext->itsPrev = this; + itsPrev = &r; +#ifndef mutable + r.itsNext = this; +#else // for ANSI-challenged compilers + (const_cast<linked_ptr<X>*>(&r))->itsNext = this; +#endif + } +#endif // NO_MEMBER_TEMPLATES + + void release() + { // erase this from the list, delete if unique + if (unique()) delete itsPtr; + else { + itsPrev->itsNext = itsNext; + itsNext->itsPrev = itsPrev; + itsPrev = itsNext = 0; + } + itsPtr = 0; + } +}; + +} // namespace talk_base + +#endif // TALK_BASE_LINKED_PTR_H__ + |