blob: 0d5ace624cc0fa47bb438f084ef2bcd6ceb52fad [file] [log] [blame]
/* $Id$
*
* 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.
*/
#ifndef __SMARTPOINTER_H__
#define __SMARTPOINTER_H__
#include "capu/Config.h"
#include "capu/os/AtomicOperation.h"
namespace capu {
template<class T>
class SmartPointer {
public:
/**
* Default constructor
*/
SmartPointer();
/**
* Constructor
* @param pointer to object
*/
SmartPointer(T* ptr);
/**
* Copy constructor for different, but castable type
* @param reference to smartPointer
*/
template<class X> friend class SmartPointer;
template<class X>
SmartPointer(const SmartPointer<X>& smartPointer);
/**
* Copy constructor
* @param reference to smartPointer
*/
SmartPointer(const SmartPointer& smartPointer);
/**
* Deconstructor
*/
~SmartPointer();
/**
* Overload assignment operator to be able to decrement the
* reference count if another object gets assigned to this smart pointer
* @param reference to smartPointer
*/
SmartPointer& operator= (const SmartPointer& smartPointer);
/**
* Overload assignment operator for castable, but different type
* @param reference to smartPointer
*/
template <class X>
SmartPointer<T>& operator= (const SmartPointer<X>& smartPointer);
/**
* Overload assignment operator to be able to decrement the
* reference count if another object gets assigned to this smart pointer
*/
SmartPointer& operator= (T* ptr);
/**
* Overload file operator to be able to access the object
* referenced by the pointer
*/
T* operator->() const;
/**
* Overload dereference operator to be able to get the object
* referenced by the pointer. Use with care!
*/
T& operator*() const;
/**
* Returns true if two smart pointer are equal to each other
* false otherwise
*/
capu::bool_t operator==(const SmartPointer<T>& x) const;
/**
* Returns true if two smart pointer aren't equal to each other
* false otherwise
*/
capu::bool_t operator!=(const SmartPointer<T>& x) const;
/**
* Returns the object stored by the smartPointer
*/
T* get() const;
/**
* Check if object exists
* @return true if object exists
*/
operator bool();
/**
* Returns the reference counter value.
* If the object does not exist, 0 ist returned
* @return reference count
*/
capu::uint32_t getRefCount();
/**
* cast a SmartPointer of type X to type T
* this is a simple C-cast, so there are no type checks
* @param reference to smartPointer
*/
template<class X>
SmartPointer<X> unchecked_cast();
private:
T* mData;
capu::uint32_t* mReferenceCount;
void incRefCount();
void decRefCount();
void freeData();
};
template<class T>
inline
SmartPointer<T>::SmartPointer()
: mData(0)
, mReferenceCount(0) {
}
template<class T>
inline
SmartPointer<T>::SmartPointer(T* ptr)
: mData(0)
, mReferenceCount(0) {
if (mData != ptr) {
mData = ptr;
mReferenceCount = new capu::uint32_t(0);
incRefCount();
}
}
template<class T>
template<class X>
inline
SmartPointer<T>::SmartPointer(const SmartPointer<X>& smartPointer)
: mData(static_cast<T*> (smartPointer.mData))
, mReferenceCount(smartPointer.mReferenceCount)
{
incRefCount();
}
template<class T>
inline
SmartPointer<T>::SmartPointer(const SmartPointer<T>& smartPointer)
: mData(smartPointer.mData)
, mReferenceCount(smartPointer.mReferenceCount) {
incRefCount();
}
template<class T>
inline
SmartPointer<T>::~SmartPointer() {
decRefCount();
}
template<class T>
inline
SmartPointer<T>& SmartPointer<T>::operator=(const SmartPointer<T>& smartPointer) {
if (this != &smartPointer) {
decRefCount();
mData = smartPointer.mData;
mReferenceCount = smartPointer.mReferenceCount;
incRefCount();
}
return *this;
}
template<class T>
inline
SmartPointer<T>& SmartPointer<T>::operator=(T* ptr) {
if (mData != ptr) {
decRefCount();
mData = ptr;
mReferenceCount = new capu::uint32_t(0);
incRefCount();
}
return *this;
}
template <class T>
template <class X>
inline
SmartPointer<T>& SmartPointer<T>::operator= (const SmartPointer<X>& smartPointer) {
if (*this != smartPointer) {
decRefCount();
mData = static_cast<T*> (smartPointer.mData);
mReferenceCount = smartPointer.mReferenceCount;
incRefCount();
}
return *this;
}
template<class T>
inline
T* SmartPointer<T>::operator->() const {
return mData;
}
template<class T>
inline
T& SmartPointer<T>::operator*() const {
return *mData;
}
template<class T>
capu::bool_t SmartPointer<T>::operator==(const SmartPointer<T>& x) const {
return ((x.mData == this->mData) && (x.mReferenceCount == this->mReferenceCount));
}
template<class T>
capu::bool_t SmartPointer<T>::operator!=(const SmartPointer<T>& x) const {
return ((x.mData != this->mData) || (x.mReferenceCount != this->mReferenceCount));
}
template<class T>
inline
void SmartPointer<T>::incRefCount() {
if (mReferenceCount) {
capu::AtomicOperation::AtomicInc32(*mReferenceCount);
}
}
template<class T>
inline
void SmartPointer<T>::decRefCount() {
if (mReferenceCount) {
uint32_t oldValue = capu::AtomicOperation::AtomicDec32(*mReferenceCount);
if (--oldValue == 0) {
freeData();
}
}
}
template<class T>
inline
void SmartPointer<T>::freeData() {
delete mData;
delete mReferenceCount;
mData = 0;
mReferenceCount = 0;
}
template<class T>
inline
T* SmartPointer<T>::get() const {
return mData;
}
template<class T>
inline
SmartPointer<T>::operator bool() {
return mData != 0;
}
template<class T>
inline
capu::uint32_t SmartPointer<T>::getRefCount() {
if (mReferenceCount != 0)
return *mReferenceCount;
else
return 0;
}
template<class T>
template<class X>
inline
SmartPointer<X> SmartPointer<T>::unchecked_cast()
{
SmartPointer<X> p;
p.mData = (X*)mData;
p.mReferenceCount = mReferenceCount;
incRefCount();
return p;
}
template<class X, class T>
SmartPointer<X> smartpointer_cast(SmartPointer<T>& ptr)
{
return ptr.template unchecked_cast<X>();
}
}
#endif // __SMARTPOINTER_H__