blob: c14759a3b670093f90cd1ba6455e9eb7e9c97076 [file] [log] [blame]
/** @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