diff options
Diffstat (limited to 'src/corelib/tools/qlist.h')
-rw-r--r-- | src/corelib/tools/qlist.h | 74 |
1 files changed, 47 insertions, 27 deletions
diff --git a/src/corelib/tools/qlist.h b/src/corelib/tools/qlist.h index 3d55b3002d..0d5b109f2f 100644 --- a/src/corelib/tools/qlist.h +++ b/src/corelib/tools/qlist.h @@ -46,15 +46,13 @@ #include <QtCore/qiterator.h> #include <QtCore/qrefcount.h> -#ifndef QT_NO_STL #include <iterator> #include <list> -#endif #ifdef Q_COMPILER_INITIALIZER_LISTS -#include <iterator> #include <initializer_list> #endif +#include <stdlib.h> #include <new> #include <limits.h> #include <string.h> @@ -71,7 +69,6 @@ struct Q_CORE_EXPORT QListData { struct Data { QtPrivate::RefCount ref; int alloc, begin, end; - uint sharable : 1; void *array[1]; }; enum { DataHeaderSize = sizeof(Data) - sizeof(void *) }; @@ -114,7 +111,7 @@ class QList public: inline QList() : d(const_cast<QListData::Data *>(&QListData::shared_null)) { } - inline QList(const QList<T> &l) : d(l.d) { d->ref.ref(); if (!d->sharable) detach_helper(); } + QList(const QList<T> &l); ~QList(); QList<T> &operator=(const QList<T> &l); #ifdef Q_COMPILER_RVALUE_REFS @@ -132,17 +129,25 @@ public: inline int size() const { return p.size(); } - inline void detach() { if (d->ref != 1) detach_helper(); } + inline void detach() { if (d->ref.isShared()) detach_helper(); } inline void detachShared() { // The "this->" qualification is needed for GCCE. - if (d->ref != 1 && this->d != &QListData::shared_null) + if (d->ref.isShared() && this->d != &QListData::shared_null) detach_helper(); } - inline bool isDetached() const { return d->ref == 1; } - inline void setSharable(bool sharable) { if (!sharable) detach(); if (d != &QListData::shared_null) d->sharable = sharable; } + inline bool isDetached() const { return !d->ref.isShared(); } + inline void setSharable(bool sharable) + { + if (sharable == d->ref.isSharable()) + return; + if (!sharable) + detach(); + if (d != &QListData::shared_null) + d->ref.setSharable(sharable); + } inline bool isSharedWith(const QList<T> &other) const { return d == other.d; } inline bool isEmpty() const { return p.isEmpty(); } @@ -325,12 +330,10 @@ public: static QList<T> fromVector(const QVector<T> &vector); static QList<T> fromSet(const QSet<T> &set); -#ifndef QT_NO_STL static inline QList<T> fromStdList(const std::list<T> &list) { QList<T> tmp; qCopy(list.begin(), list.end(), std::back_inserter(tmp)); return tmp; } inline std::list<T> toStdList() const { std::list<T> tmp; qCopy(constBegin(), constEnd(), std::back_inserter(tmp)); return tmp; } -#endif private: Node *detach_helper_grow(int i, int n); @@ -421,13 +424,8 @@ template <typename T> Q_INLINE_TEMPLATE QList<T> &QList<T>::operator=(const QList<T> &l) { if (d != l.d) { - QListData::Data *o = l.d; - o->ref.ref(); - if (!d->ref.deref()) - dealloc(d); - d = o; - if (!d->sharable) - detach_helper(); + QList<T> tmp(l); + tmp.swap(*this); } return *this; } @@ -480,7 +478,7 @@ template <typename T> Q_OUTOFLINE_TEMPLATE void QList<T>::reserve(int alloc) { if (d->alloc < alloc) { - if (d->ref != 1) + if (d->ref.isShared()) detach_helper(alloc); else p.realloc(alloc); @@ -490,7 +488,7 @@ Q_OUTOFLINE_TEMPLATE void QList<T>::reserve(int alloc) template <typename T> Q_OUTOFLINE_TEMPLATE void QList<T>::append(const T &t) { - if (d->ref != 1) { + if (d->ref.isShared()) { Node *n = detach_helper_grow(INT_MAX, 1); QT_TRY { node_construct(n, t); @@ -524,7 +522,7 @@ Q_OUTOFLINE_TEMPLATE void QList<T>::append(const T &t) template <typename T> inline void QList<T>::prepend(const T &t) { - if (d->ref != 1) { + if (d->ref.isShared()) { Node *n = detach_helper_grow(0, 1); QT_TRY { node_construct(n, t); @@ -558,7 +556,7 @@ inline void QList<T>::prepend(const T &t) template <typename T> inline void QList<T>::insert(int i, const T &t) { - if (d->ref != 1) { + if (d->ref.isShared()) { Node *n = detach_helper_grow(i, 1); QT_TRY { node_construct(n, t); @@ -665,7 +663,7 @@ Q_OUTOFLINE_TEMPLATE typename QList<T>::Node *QList<T>::detach_helper_grow(int i node_copy(reinterpret_cast<Node *>(p.begin()), reinterpret_cast<Node *>(p.begin() + i), n); } QT_CATCH(...) { - qFree(d); + free(d); d = x; QT_RETHROW; } @@ -675,7 +673,7 @@ Q_OUTOFLINE_TEMPLATE typename QList<T>::Node *QList<T>::detach_helper_grow(int i } QT_CATCH(...) { node_destruct(reinterpret_cast<Node *>(p.begin()), reinterpret_cast<Node *>(p.begin() + i)); - qFree(d); + free(d); d = x; QT_RETHROW; } @@ -694,7 +692,7 @@ Q_OUTOFLINE_TEMPLATE void QList<T>::detach_helper(int alloc) QT_TRY { node_copy(reinterpret_cast<Node *>(p.begin()), reinterpret_cast<Node *>(p.end()), n); } QT_CATCH(...) { - qFree(d); + free(d); d = x; QT_RETHROW; } @@ -710,6 +708,28 @@ Q_OUTOFLINE_TEMPLATE void QList<T>::detach_helper() } template <typename T> +Q_OUTOFLINE_TEMPLATE QList<T>::QList(const QList<T> &l) + : d(l.d) +{ + if (!d->ref.ref()) { + p.detach(d->alloc); + + struct Cleanup + { + Cleanup(QListData::Data *d) : d_(d) {} + ~Cleanup() { if (d_) free(d_); } + + QListData::Data *d_; + } tryCatch(d); + + node_copy(reinterpret_cast<Node *>(p.begin()), + reinterpret_cast<Node *>(p.end()), + reinterpret_cast<Node *>(l.p.begin())); + tryCatch.d_ = 0; + } +} + +template <typename T> Q_OUTOFLINE_TEMPLATE QList<T>::~QList() { if (!d->ref.deref()) @@ -739,7 +759,7 @@ Q_OUTOFLINE_TEMPLATE void QList<T>::dealloc(QListData::Data *data) { node_destruct(reinterpret_cast<Node *>(data->array + data->begin), reinterpret_cast<Node *>(data->array + data->end)); - qFree(data); + free(data); } @@ -804,7 +824,7 @@ Q_OUTOFLINE_TEMPLATE QList<T> &QList<T>::operator+=(const QList<T> &l) if (isEmpty()) { *this = l; } else { - Node *n = (d->ref != 1) + Node *n = (d->ref.isShared()) ? detach_helper_grow(INT_MAX, l.size()) : reinterpret_cast<Node *>(p.append(l.p)); QT_TRY { |