kdelibs/kdecore/util/ksharedptr.h
Ivailo Monev 1f34f5ad73 generic: use CMake export header generator
Signed-off-by: Ivailo Monev <xakepa10@gmail.com>
2016-04-27 20:13:02 +00:00

219 lines
6.9 KiB
C++

/*
* This file is part of the KDE libraries.
*
* Copyright 2005 Frerich Raabe <raabe@kde.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef KSHAREDPTR_H
#define KSHAREDPTR_H
#include <QtCore/qsharedpointer.h>
#include <QtCore/qatomic.h>
/**
* \class KSharedPtr ksharedptr.h <KSharedPtr>
*
* Can be used to control the lifetime of an object that has derived
* QSharedData. As long a someone holds
* a KSharedPtr on some QSharedData object it won't become deleted but
* is deleted once its reference count is 0.
* This struct emulates C++ pointers virtually perfectly.
* So just use it like a simple C++ pointer.
*
* The difference with QSharedPointer is that QSharedPointer does the refcounting
* in the pointer, while KSharedPtr does the refcounting in the object.
* This allows to convert to a raw pointer temporarily and back to a KSharedPtr
* without deleting the object, if another reference exists. But it imposes a
* requirement on the object, which must inherit QSharedData.
*
* The difference with using QSharedDataPointer is that QSharedDataPointer is
* a building block for implementing a value class with implicit sharing (like QString),
* whereas KSharedPtr provides refcounting to code that uses pointers.
*
* @author Waldo Bastian <bastian@kde.org>
*/
template< class T >
class KSharedPtr
{
public:
/**
* Creates a null pointer.
*/
inline KSharedPtr()
: d(0) { }
/**
* Creates a new pointer.
* @param p the pointer
*/
inline explicit KSharedPtr( T* p )
: d(p) { if(d) d->ref.ref(); }
/**
* Copies a pointer.
* @param o the pointer to copy
*/
inline KSharedPtr( const KSharedPtr& o )
: d(o.d) { if(d) d->ref.ref(); }
/**
* Unreferences the object that this pointer points to. If it was
* the last reference, the object will be deleted.
*/
inline ~KSharedPtr() { if (d && !d->ref.deref()) delete d; }
inline KSharedPtr<T>& operator= ( const KSharedPtr& o ) { attach(o.d); return *this; }
inline bool operator== ( const KSharedPtr& o ) const { return ( d == o.d ); }
inline bool operator!= ( const KSharedPtr& o ) const { return ( d != o.d ); }
inline bool operator< ( const KSharedPtr& o ) const { return ( d < o.d ); }
inline KSharedPtr<T>& operator= ( T* p ) { attach(p); return *this; }
inline bool operator== ( const T* p ) const { return ( d == p ); }
inline bool operator!= ( const T* p ) const { return ( d != p ); }
/**
* Test if the shared pointer is NOT null.
* @return true if the shared pointer is NOT null, false otherwise.
* @see isNull
*/
inline operator bool() const { return ( d != 0 ); }
/**
* @return the pointer
*/
inline T* data() { return d; }
/**
* @return the pointer
*/
inline const T* data() const { return d; }
/**
* @return a const pointer to the shared object.
*/
inline const T* constData() const { return d; }
inline const T& operator*() const { Q_ASSERT(d); return *d; }
inline T& operator*() { Q_ASSERT(d); return *d; }
inline const T* operator->() const { Q_ASSERT(d); return d; }
inline T* operator->() { Q_ASSERT(d); return d; }
/**
* Attach the given pointer to the current KSharedPtr.
* If the previous shared pointer is not owned by any KSharedPtr,
* it is deleted.
*/
void attach(T* p);
/**
* Clear the pointer, i.e. make it a null pointer.
*/
void clear();
/**
* Returns the number of references.
* @return the number of references
*/
inline int count() const { return d ? static_cast<int>(d->ref) : 0; } // for debugging purposes
/**
* Test if the shared pointer is null.
* @return true if the pointer is null, false otherwise.
* @see opertor (bool)
*/
inline bool isNull() const { return (d == 0); }
/**
* @return Whether this is the only shared pointer pointing to
* to the pointee, or whether it's shared among multiple
* shared pointers.
*/
inline bool isUnique() const { return count() == 1; }
template <class U> friend class KSharedPtr;
/**
* Convert KSharedPtr<U> to KSharedPtr<T>, using a static_cast.
* This will compile whenever T* and U* are compatible, i.e.
* T is a subclass of U or vice-versa.
* Example syntax:
* <code>
* KSharedPtr<T> tPtr;
* KSharedPtr<U> uPtr = KSharedPtr<U>::staticCast( tPtr );
* </code>
*/
template <class U>
static KSharedPtr<T> staticCast( const KSharedPtr<U>& o ) {
return KSharedPtr<T>( static_cast<T *>( o.d ) );
}
/**
* Convert KSharedPtr<U> to KSharedPtr<T>, using a dynamic_cast.
* This will compile whenever T* and U* are compatible, i.e.
* T is a subclass of U or vice-versa.
* Example syntax:
* <code>
* KSharedPtr<T> tPtr;
* KSharedPtr<U> uPtr = KSharedPtr<U>::dynamicCast( tPtr );
* </code>
* Since a dynamic_cast is used, if U derives from T, and tPtr isn't an instance of U, uPtr will be 0.
*/
template <class U>
static KSharedPtr<T> dynamicCast( const KSharedPtr<U>& o ) {
return KSharedPtr<T>( dynamic_cast<T *>( o.d ) );
}
protected:
T* d;
};
template <class T>
Q_INLINE_TEMPLATE bool operator== (const T* p, const KSharedPtr<T>& o)
{
return ( o == p );
}
template <class T>
Q_INLINE_TEMPLATE bool operator!= (const T* p, const KSharedPtr<T>& o)
{
return ( o != p );
}
template <class T>
Q_INLINE_TEMPLATE void KSharedPtr<T>::attach(T* p)
{
if (d != p) {
if (p) p->ref.ref();
if (d && !d->ref.deref())
delete d;
d = p;
}
}
template <class T>
Q_INLINE_TEMPLATE void KSharedPtr<T>::clear()
{
attach(static_cast<T*>(0));
}
#endif