| /** @file |
| |
| A brief file description |
| |
| @section license License |
| |
| Licensed to the Apache Software Foundation (ASF) under one |
| or more contributor license agreements. See the NOTICE file |
| distributed with this work for additional information |
| regarding copyright ownership. The ASF licenses this file |
| to you under the Apache License, Version 2.0 (the |
| "License"); you may not use this file except in compliance |
| with the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| */ |
| |
| /*************************** -*- Mod: C++ -*- ****************************** |
| |
| Atmic and non-atomic smart pointers. |
| |
| Note: it would have been nice to have one 'Ptr' class, but the |
| templating system on some compilers is so broken that it cannot |
| correctly compile Ptr without downcasting the m_ptr object to |
| a RefCountObj. |
| |
| |
| ****************************************************************************/ |
| #if !defined (_Ptr_h_) |
| #define _Ptr_h_ |
| |
| #include "ink_atomic.h" |
| |
| //////////////////////////////////////////////////////////////////////// |
| // |
| // class NonAtomicRefCountObj |
| // prototypical class for reference counting |
| // |
| //////////////////////////////////////////////////////////////////////// |
| class NonAtomicRefCountObj |
| { |
| public: |
| NonAtomicRefCountObj():m_refcount(0) |
| { |
| return; |
| } |
| NonAtomicRefCountObj(const NonAtomicRefCountObj & s):m_refcount(0) |
| { |
| (void) s; |
| return; |
| } |
| virtual ~ NonAtomicRefCountObj() { |
| return; |
| } |
| NonAtomicRefCountObj & operator =(const NonAtomicRefCountObj & s) { |
| (void) s; |
| return (*this); |
| } |
| |
| int refcount_inc(); |
| int refcount_dec(); |
| int refcount() const; |
| |
| virtual void free() |
| { |
| delete this; |
| } |
| |
| volatile int m_refcount; |
| }; |
| |
| inline int |
| NonAtomicRefCountObj::refcount_inc() |
| { |
| return ++m_refcount; |
| } |
| |
| #define NONATOMIC_REF_COUNT_OBJ_REFCOUNT_INC(_x) (_x)->refcount_inc() |
| |
| inline int |
| NonAtomicRefCountObj::refcount_dec() |
| { |
| return --m_refcount; |
| } |
| |
| #define NONATOMIC_REF_COUNT_OBJ_REFCOUNT_DEC(_x) (_x)->refcount_dec() |
| |
| inline int |
| NonAtomicRefCountObj::refcount() const |
| { |
| return m_refcount; |
| } |
| |
| |
| |
| //////////////////////////////////////////////////////////////////////// |
| // |
| // class NonAtomicPtr |
| // |
| //////////////////////////////////////////////////////////////////////// |
| template<class T> class NonAtomicPtr { |
| public: |
| explicit NonAtomicPtr(T * ptr = 0); |
| NonAtomicPtr(const NonAtomicPtr<T> &); |
| ~NonAtomicPtr(); |
| |
| NonAtomicPtr<T> &operator =(const NonAtomicPtr<T> &); |
| NonAtomicPtr<T> &operator =(T *); |
| |
| void clear(); |
| |
| operator T *() const |
| { |
| return (m_ptr); |
| } |
| T *operator ->() const |
| { |
| return (m_ptr); |
| } |
| T & operator *() const |
| { |
| return (*m_ptr); |
| } |
| |
| int operator ==(const T * p) |
| { |
| return (m_ptr == p); |
| } |
| int operator ==(const NonAtomicPtr<T> &p) |
| { |
| return (m_ptr == p.m_ptr); |
| } |
| int operator !=(const T * p) |
| { |
| return (m_ptr != p); |
| } |
| int operator !=(const NonAtomicPtr<T> &p) |
| { |
| return (m_ptr != p.m_ptr); |
| } |
| |
| NonAtomicRefCountObj *_ptr() |
| { |
| return (NonAtomicRefCountObj *) m_ptr; |
| } |
| |
| T *m_ptr; |
| }; |
| |
| template <typename T> |
| NonAtomicPtr<T> make_nonatomic_ptr(T * p) { |
| return NonAtomicPtr<T>(p); |
| } |
| |
| //////////////////////////////////////////////////////////////////////// |
| // |
| // inline functions definitions |
| // |
| //////////////////////////////////////////////////////////////////////// |
| template<class T> inline NonAtomicPtr<T>::NonAtomicPtr(T * ptr /* = 0 */ ) |
| : |
| m_ptr(ptr) |
| { |
| if (m_ptr) |
| _ptr()->refcount_inc(); |
| return; |
| } |
| |
| template<class T> inline NonAtomicPtr<T>::NonAtomicPtr(const NonAtomicPtr<T> &src) |
| : |
| m_ptr(src.m_ptr) |
| { |
| if (m_ptr) |
| _ptr()->refcount_inc(); |
| return; |
| } |
| |
| template<class T> inline NonAtomicPtr<T>::~NonAtomicPtr() |
| { |
| if ((m_ptr) && _ptr()->refcount_dec() == 0) { |
| _ptr()->free(); |
| } |
| return; |
| } |
| |
| template<class T> inline NonAtomicPtr<T> &NonAtomicPtr<T>::operator =(T * p) |
| { |
| T *temp_ptr = m_ptr; |
| |
| if (m_ptr == p) |
| return (*this); |
| |
| m_ptr = p; |
| |
| if (m_ptr != 0) { |
| _ptr()->refcount_inc(); |
| } |
| |
| if ((temp_ptr) && ((NonAtomicRefCountObj *) temp_ptr)->refcount_dec() == 0) { |
| ((NonAtomicRefCountObj *) temp_ptr)->free(); |
| } |
| |
| return (*this); |
| } |
| template<class T> inline void NonAtomicPtr<T>::clear() |
| { |
| if (m_ptr) { |
| if (!((NonAtomicRefCountObj *) m_ptr)->refcount_dec()) |
| ((NonAtomicRefCountObj *) m_ptr)->free(); |
| m_ptr = NULL; |
| } |
| } |
| template<class T> inline NonAtomicPtr<T> &NonAtomicPtr<T>::operator =(const NonAtomicPtr<T> &src) |
| { |
| return (operator =(src.m_ptr)); |
| } |
| |
| |
| //////////////////////////////////////////////////////////////////// |
| //////////////////////////////////////////////////////////////////// |
| ////// ATOMIC VERSIONS |
| //////////////////////////////////////////////////////////////////// |
| //////////////////////////////////////////////////////////////////// |
| |
| struct ForceVFPTToTop |
| { |
| virtual ~ ForceVFPTToTop() |
| { |
| } |
| }; |
| |
| |
| //////////////////////////////////////////////////////////////////////// |
| // |
| // class RefCountObj |
| // prototypical class for reference counting |
| // |
| //////////////////////////////////////////////////////////////////////// |
| class RefCountObj: public ForceVFPTToTop |
| { |
| public: |
| RefCountObj():m_refcount(0) |
| { |
| } |
| RefCountObj(const RefCountObj & s):m_refcount(0) |
| { |
| (void) s; |
| return; |
| } |
| virtual ~ RefCountObj() { |
| } |
| RefCountObj & operator =(const RefCountObj & s) { |
| (void) s; |
| return (*this); |
| } |
| |
| int refcount_inc(); |
| int refcount_dec(); |
| int refcount() const; |
| |
| virtual void free() |
| { |
| delete this; |
| } |
| |
| volatile int m_refcount; |
| }; |
| |
| inline int |
| RefCountObj::refcount_inc() |
| { |
| return ink_atomic_increment((int *) &m_refcount, 1) + 1; |
| } |
| |
| #define REF_COUNT_OBJ_REFCOUNT_INC(_x) (_x)->refcount_inc() |
| |
| inline int |
| RefCountObj::refcount_dec() |
| { |
| return ink_atomic_increment((int *) &m_refcount, -1) - 1; |
| } |
| |
| #define REF_COUNT_OBJ_REFCOUNT_DEC(_x) (_x)->refcount_dec() |
| |
| inline int |
| RefCountObj::refcount() const |
| { |
| return m_refcount; |
| } |
| |
| |
| //////////////////////////////////////////////////////////////////////// |
| // |
| // class Ptr |
| // |
| //////////////////////////////////////////////////////////////////////// |
| template<class T> class Ptr { |
| public: |
| explicit Ptr(T * p = 0); |
| Ptr(const Ptr<T> &); |
| ~Ptr(); |
| |
| void clear(); |
| Ptr<T> &operator =(const Ptr<T> &); |
| Ptr<T> &operator =(T *); |
| |
| T * to_ptr() { |
| if (m_ptr && m_ptr->m_refcount == 1) { |
| T * ptr = m_ptr; |
| m_ptr = 0; |
| ptr->m_refcount = 0; |
| return ptr; |
| } |
| return 0; |
| } |
| operator T *() const |
| { |
| return (m_ptr); |
| } |
| T *operator ->() const |
| { |
| return (m_ptr); |
| } |
| T & operator *() const |
| { |
| return (*m_ptr); |
| } |
| |
| int operator ==(const T * p) |
| { |
| return (m_ptr == p); |
| } |
| int operator ==(const Ptr<T> &p) |
| { |
| return (m_ptr == p.m_ptr); |
| } |
| int operator !=(const T * p) |
| { |
| return (m_ptr != p); |
| } |
| int operator !=(const Ptr<T> &p) |
| { |
| return (m_ptr != p.m_ptr); |
| } |
| |
| RefCountObj *_ptr() |
| { |
| return (RefCountObj *) m_ptr; |
| } |
| |
| T *m_ptr; |
| }; |
| |
| template <typename T> |
| Ptr<T> make_ptr(T * p) { |
| return Ptr<T>(p); |
| } |
| |
| //////////////////////////////////////////////////////////////////////// |
| // |
| // inline functions definitions |
| // |
| //////////////////////////////////////////////////////////////////////// |
| template<class T> inline Ptr<T>::Ptr(T * ptr /* = 0 */ ) |
| : |
| m_ptr(ptr) |
| { |
| if (m_ptr) |
| _ptr()->refcount_inc(); |
| return; |
| } |
| |
| template<class T> inline Ptr<T>::Ptr(const Ptr<T> &src) |
| : |
| m_ptr(src.m_ptr) |
| { |
| if (m_ptr) |
| _ptr()->refcount_inc(); |
| return; |
| } |
| |
| template<class T> inline Ptr<T>::~Ptr() |
| { |
| if ((m_ptr) && _ptr()->refcount_dec() == 0) { |
| _ptr()->free(); |
| } |
| return; |
| } |
| |
| template<class T> inline Ptr<T> &Ptr<T>::operator =(T * p) |
| { |
| T *temp_ptr = m_ptr; |
| |
| if (m_ptr == p) |
| return (*this); |
| |
| m_ptr = p; |
| |
| if (m_ptr != 0) { |
| _ptr()->refcount_inc(); |
| } |
| |
| if ((temp_ptr) && ((RefCountObj *) temp_ptr)->refcount_dec() == 0) { |
| ((RefCountObj *) temp_ptr)->free(); |
| } |
| |
| return (*this); |
| } |
| template<class T> inline void Ptr<T>::clear() |
| { |
| if (m_ptr) { |
| if (!((RefCountObj *) m_ptr)->refcount_dec()) |
| ((RefCountObj *) m_ptr)->free(); |
| m_ptr = NULL; |
| } |
| } |
| template<class T> inline Ptr<T> &Ptr<T>::operator =(const Ptr<T> &src) |
| { |
| return (operator =(src.m_ptr)); |
| } |
| |
| #endif |