Now merge the QtShared::ExternalRefCount class into QSharedPointer
Completing the work of the previous commit: we don't need separate classes. Merge into the main class's body. Change-Id: I2f89b34cb6b7f5f9e8d8b809bebd86656f458644 Reviewed-by: Lars Knoll <lars.knoll@nokia.com> Reviewed-by: Bradley T. Hughes <bradley.hughes@nokia.com>
This commit is contained in:
parent
32edd16e2b
commit
086d6e74d2
@ -268,14 +268,12 @@ namespace QtSharedPointer {
|
||||
~ExternalRefCountWithContiguousData() Q_DECL_EQ_DELETE;
|
||||
Q_DISABLE_COPY(ExternalRefCountWithContiguousData)
|
||||
};
|
||||
} // namespace QtSharedPointer
|
||||
|
||||
// This is the main body of QSharedPointer. It implements the
|
||||
// external reference counting functionality.
|
||||
template <class T>
|
||||
class ExternalRefCount
|
||||
template <class T> class QSharedPointer
|
||||
{
|
||||
typedef T *ExternalRefCount:: *RestrictedBool;
|
||||
typedef ExternalRefCountData Data;
|
||||
typedef T *QSharedPointer:: *RestrictedBool;
|
||||
typedef QtSharedPointer::ExternalRefCountData Data;
|
||||
public:
|
||||
typedef T Type;
|
||||
typedef T element_type;
|
||||
@ -288,143 +286,26 @@ namespace QtSharedPointer {
|
||||
|
||||
inline T *data() const { return value; }
|
||||
inline bool isNull() const { return !data(); }
|
||||
inline operator RestrictedBool() const { return isNull() ? 0 : &ExternalRefCount::value; }
|
||||
inline operator RestrictedBool() const { return isNull() ? 0 : &QSharedPointer::value; }
|
||||
inline bool operator !() const { return isNull(); }
|
||||
inline T &operator*() const { return *data(); }
|
||||
inline T *operator->() const { return data(); }
|
||||
|
||||
protected:
|
||||
inline void deref()
|
||||
{ deref(d); }
|
||||
static inline void deref(Data *d)
|
||||
{
|
||||
if (!d) return;
|
||||
if (!d->strongref.deref()) {
|
||||
d->destroy();
|
||||
}
|
||||
if (!d->weakref.deref())
|
||||
delete d;
|
||||
}
|
||||
QSharedPointer() : value(0), d(0) { }
|
||||
~QSharedPointer() { deref(); }
|
||||
|
||||
inline explicit QSharedPointer(T *ptr) // throws
|
||||
{ internalConstruct(ptr, &QtSharedPointer::normalDeleter<T>); }
|
||||
|
||||
template <typename Deleter>
|
||||
inline void internalConstruct(T *ptr, Deleter deleter)
|
||||
{
|
||||
if (ptr)
|
||||
d = ExternalRefCountWithCustomDeleter<T, Deleter>::create(ptr, deleter);
|
||||
else
|
||||
d = 0;
|
||||
internalFinishConstruction(ptr);
|
||||
}
|
||||
|
||||
inline void internalCreate()
|
||||
{
|
||||
d = ExternalRefCountWithContiguousData<T>::create(&value);
|
||||
}
|
||||
|
||||
inline void internalFinishConstruction(T *ptr)
|
||||
{
|
||||
value = ptr;
|
||||
if (ptr) d->setQObjectShared(ptr, true);
|
||||
#ifdef QT_SHAREDPOINTER_TRACK_POINTERS
|
||||
if (ptr) internalSafetyCheckAdd(d, ptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline ExternalRefCount() : value(0), d(0) { }
|
||||
inline ExternalRefCount(Qt::Initialization) { }
|
||||
|
||||
template <typename Deleter>
|
||||
inline ExternalRefCount(T *ptr, Deleter deleter) // throws
|
||||
inline QSharedPointer(T *ptr, Deleter deleter) : value(ptr) // throws
|
||||
{ internalConstruct(ptr, deleter); }
|
||||
|
||||
inline ExternalRefCount(const ExternalRefCount<T> &other) : value(other.value), d(other.d)
|
||||
inline QSharedPointer(const QSharedPointer<T> &other) : value(other.value), d(other.d)
|
||||
{ if (d) ref(); }
|
||||
template <class X>
|
||||
inline ExternalRefCount(const ExternalRefCount<X> &other) : value(other.value), d(other.d)
|
||||
{ if (d) ref(); }
|
||||
inline ~ExternalRefCount() { deref(); }
|
||||
|
||||
template <class X>
|
||||
inline void internalCopy(const ExternalRefCount<X> &other)
|
||||
{
|
||||
Data *o = other.d;
|
||||
T *actual = other.value;
|
||||
if (o)
|
||||
other.ref();
|
||||
qSwap(d, o);
|
||||
qSwap(this->value, actual);
|
||||
deref(o);
|
||||
}
|
||||
|
||||
inline void internalSwap(ExternalRefCount &other)
|
||||
{
|
||||
qSwap(d, other.d);
|
||||
qSwap(this->value, other.value);
|
||||
}
|
||||
|
||||
#if defined(Q_NO_TEMPLATE_FRIENDS)
|
||||
public:
|
||||
#else
|
||||
template <class X> friend class ExternalRefCount;
|
||||
template <class X> friend class QT_PREPEND_NAMESPACE(QWeakPointer);
|
||||
template <class X, class Y> friend QSharedPointer<X> copyAndSetPointer(X * ptr, const QSharedPointer<Y> &src);
|
||||
#endif
|
||||
inline void ref() const { d->weakref.ref(); d->strongref.ref(); }
|
||||
|
||||
inline void internalSet(Data *o, T *actual)
|
||||
{
|
||||
if (o) {
|
||||
// increase the strongref, but never up from zero
|
||||
// or less (-1 is used by QWeakPointer on untracked QObject)
|
||||
register int tmp = o->strongref.load();
|
||||
while (tmp > 0) {
|
||||
// try to increment from "tmp" to "tmp + 1"
|
||||
if (o->strongref.testAndSetRelaxed(tmp, tmp + 1))
|
||||
break; // succeeded
|
||||
tmp = o->strongref.load(); // failed, try again
|
||||
}
|
||||
|
||||
if (tmp > 0) {
|
||||
o->weakref.ref();
|
||||
} else {
|
||||
o->checkQObjectShared(actual);
|
||||
o = 0;
|
||||
}
|
||||
}
|
||||
|
||||
qSwap(d, o);
|
||||
qSwap(this->value, actual);
|
||||
if (!d || d->strongref.load() == 0)
|
||||
this->value = 0;
|
||||
|
||||
// dereference saved data
|
||||
deref(o);
|
||||
}
|
||||
|
||||
Type *value;
|
||||
Data *d;
|
||||
};
|
||||
} // namespace QtSharedPointer
|
||||
|
||||
template <class T>
|
||||
class QSharedPointer: public QtSharedPointer::ExternalRefCount<T>
|
||||
{
|
||||
typedef typename QtSharedPointer::ExternalRefCount<T> BaseClass;
|
||||
public:
|
||||
inline QSharedPointer() { }
|
||||
// inline ~QSharedPointer() { }
|
||||
|
||||
inline explicit QSharedPointer(T *ptr) : BaseClass(ptr, &QtSharedPointer::normalDeleter<T>) // throws
|
||||
{ }
|
||||
|
||||
template <typename Deleter>
|
||||
inline QSharedPointer(T *ptr, Deleter d) : BaseClass(ptr, d) // throws
|
||||
{ }
|
||||
|
||||
inline QSharedPointer(const QSharedPointer<T> &other) : BaseClass(other) { }
|
||||
inline QSharedPointer<T> &operator=(const QSharedPointer<T> &other)
|
||||
{
|
||||
BaseClass::internalCopy(other);
|
||||
internalCopy(other);
|
||||
return *this;
|
||||
}
|
||||
#ifdef Q_COMPILER_RVALUE_REFS
|
||||
@ -436,24 +317,24 @@ public:
|
||||
#endif
|
||||
|
||||
template <class X>
|
||||
inline QSharedPointer(const QSharedPointer<X> &other) : BaseClass(other)
|
||||
{ }
|
||||
inline QSharedPointer(const QSharedPointer<X> &other) : value(other.value), d(other.d)
|
||||
{ if (d) ref(); }
|
||||
|
||||
template <class X>
|
||||
inline QSharedPointer<T> &operator=(const QSharedPointer<X> &other)
|
||||
{
|
||||
QSHAREDPOINTER_VERIFY_AUTO_CAST(T, X); // if you get an error in this line, the cast is invalid
|
||||
BaseClass::internalCopy(other);
|
||||
internalCopy(other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class X>
|
||||
inline QSharedPointer(const QWeakPointer<X> &other) : BaseClass(Qt::Uninitialized)
|
||||
{ this->d = 0; *this = other; }
|
||||
inline QSharedPointer(const QWeakPointer<X> &other) : value(0), d(0)
|
||||
{ *this = other; }
|
||||
|
||||
template <class X>
|
||||
inline QSharedPointer<T> &operator=(const QWeakPointer<X> &other)
|
||||
{ BaseClass::internalSet(other.d, other.value); return *this; }
|
||||
{ internalSet(other.d, other.value); return *this; }
|
||||
|
||||
inline void swap(QSharedPointer &other)
|
||||
{ QSharedPointer<T>::internalSwap(other); }
|
||||
@ -495,10 +376,6 @@ public:
|
||||
|
||||
QWeakPointer<T> toWeakRef() const;
|
||||
|
||||
protected:
|
||||
inline explicit QSharedPointer(Qt::Initialization i) : BaseClass(i) {}
|
||||
|
||||
public:
|
||||
static inline QSharedPointer<T> create()
|
||||
{
|
||||
QSharedPointer<T> result(Qt::Uninitialized);
|
||||
@ -509,6 +386,105 @@ public:
|
||||
result.internalFinishConstruction(result.data());
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
explicit QSharedPointer(Qt::Initialization) {}
|
||||
|
||||
inline void deref()
|
||||
{ deref(d); }
|
||||
static inline void deref(Data *d)
|
||||
{
|
||||
if (!d) return;
|
||||
if (!d->strongref.deref()) {
|
||||
d->destroy();
|
||||
}
|
||||
if (!d->weakref.deref())
|
||||
delete d;
|
||||
}
|
||||
|
||||
template <typename Deleter>
|
||||
inline void internalConstruct(T *ptr, Deleter deleter)
|
||||
{
|
||||
if (ptr)
|
||||
d = QtSharedPointer::ExternalRefCountWithCustomDeleter<T, Deleter>::create(ptr, deleter);
|
||||
else
|
||||
d = 0;
|
||||
internalFinishConstruction(ptr);
|
||||
}
|
||||
|
||||
inline void internalCreate()
|
||||
{
|
||||
d = QtSharedPointer::ExternalRefCountWithContiguousData<T>::create(&value);
|
||||
}
|
||||
|
||||
inline void internalFinishConstruction(T *ptr)
|
||||
{
|
||||
value = ptr;
|
||||
if (ptr) d->setQObjectShared(ptr, true);
|
||||
#ifdef QT_SHAREDPOINTER_TRACK_POINTERS
|
||||
if (ptr) internalSafetyCheckAdd(d, ptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class X>
|
||||
inline void internalCopy(const QSharedPointer<X> &other)
|
||||
{
|
||||
Data *o = other.d;
|
||||
T *actual = other.value;
|
||||
if (o)
|
||||
other.ref();
|
||||
qSwap(d, o);
|
||||
qSwap(this->value, actual);
|
||||
deref(o);
|
||||
}
|
||||
|
||||
inline void internalSwap(QSharedPointer &other)
|
||||
{
|
||||
qSwap(d, other.d);
|
||||
qSwap(this->value, other.value);
|
||||
}
|
||||
|
||||
#if defined(Q_NO_TEMPLATE_FRIENDS)
|
||||
public:
|
||||
#else
|
||||
template <class X> friend class QSharedPointer;
|
||||
template <class X> friend class QWeakPointer;
|
||||
template <class X, class Y> friend QSharedPointer<X> QtSharedPointer::copyAndSetPointer(X * ptr, const QSharedPointer<Y> &src);
|
||||
#endif
|
||||
inline void ref() const { d->weakref.ref(); d->strongref.ref(); }
|
||||
|
||||
inline void internalSet(Data *o, T *actual)
|
||||
{
|
||||
if (o) {
|
||||
// increase the strongref, but never up from zero
|
||||
// or less (-1 is used by QWeakPointer on untracked QObject)
|
||||
register int tmp = o->strongref.load();
|
||||
while (tmp > 0) {
|
||||
// try to increment from "tmp" to "tmp + 1"
|
||||
if (o->strongref.testAndSetRelaxed(tmp, tmp + 1))
|
||||
break; // succeeded
|
||||
tmp = o->strongref.load(); // failed, try again
|
||||
}
|
||||
|
||||
if (tmp > 0) {
|
||||
o->weakref.ref();
|
||||
} else {
|
||||
o->checkQObjectShared(actual);
|
||||
o = 0;
|
||||
}
|
||||
}
|
||||
|
||||
qSwap(d, o);
|
||||
qSwap(this->value, actual);
|
||||
if (!d || d->strongref.load() == 0)
|
||||
this->value = 0;
|
||||
|
||||
// dereference saved data
|
||||
deref(o);
|
||||
}
|
||||
|
||||
Type *value;
|
||||
Data *d;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
|
@ -118,7 +118,7 @@ public:
|
||||
};
|
||||
|
||||
template<typename T> static inline
|
||||
QtSharedPointer::ExternalRefCountData *refCountData(const QtSharedPointer::ExternalRefCount<T> &b)
|
||||
QtSharedPointer::ExternalRefCountData *refCountData(const QSharedPointer<T> &b)
|
||||
{
|
||||
// access d-pointer:
|
||||
struct Dummy {
|
||||
@ -126,7 +126,7 @@ QtSharedPointer::ExternalRefCountData *refCountData(const QtSharedPointer::Exter
|
||||
QtSharedPointer::ExternalRefCountData* data;
|
||||
};
|
||||
// sanity checks:
|
||||
Q_STATIC_ASSERT(sizeof(QtSharedPointer::ExternalRefCount<T>) == sizeof(Dummy));
|
||||
Q_STATIC_ASSERT(sizeof(QSharedPointer<T>) == sizeof(Dummy));
|
||||
Q_ASSERT(static_cast<const Dummy*>(static_cast<const void*>(&b))->value == b.data());
|
||||
return static_cast<const Dummy*>(static_cast<const void*>(&b))->data;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user