diff options
author | João Abecasis <joao.abecasis@nokia.com> | 2011-11-24 17:15:11 +0100 |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2012-01-06 17:25:09 +0100 |
commit | 3d61c5ca8f00b489435d5bea776b4a4c97c39793 (patch) | |
tree | 45480cd94b6dbb0899398c0abb692bc1ebba3aca /src | |
parent | 51048e1f31df5be45e71a75fc535111dd36c4c9e (diff) |
Add setSharable support in QArrayData stack
Making use of the same feature added in RefCount.
To keep with the intention of avoiding the allocation of "empty" array
headers, this introduces an unsharable_empty, which allows users to
maintain the "unsharable bit" on empty containers, without imposing any
actual allocations.
(Before anyone asks, there is no point to a zero-sized capacity-reserved
container so no other combinations are needed for now.)
Change-Id: Icaa40ac3100ad954fdc20dee0c991861136a5b19
Reviewed-by: Bradley T. Hughes <bradley.hughes@nokia.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/corelib/tools/qarraydata.cpp | 12 | ||||
-rw-r--r-- | src/corelib/tools/qarraydata.h | 15 | ||||
-rw-r--r-- | src/corelib/tools/qarraydataops.h | 14 | ||||
-rw-r--r-- | src/corelib/tools/qarraydatapointer.h | 20 | ||||
-rw-r--r-- | src/corelib/tools/qrefcount.h | 1 |
5 files changed, 47 insertions, 15 deletions
diff --git a/src/corelib/tools/qarraydata.cpp b/src/corelib/tools/qarraydata.cpp index 1145ecb4f4..c6e96c78a9 100644 --- a/src/corelib/tools/qarraydata.cpp +++ b/src/corelib/tools/qarraydata.cpp @@ -45,9 +45,10 @@ QT_BEGIN_NAMESPACE const QArrayData QArrayData::shared_null = { Q_REFCOUNT_INITIALIZE_STATIC, 0, 0, 0, 0 }; const QArrayData QArrayData::shared_empty = { Q_REFCOUNT_INITIALIZE_STATIC, 0, 0, 0, 0 }; +const QArrayData QArrayData::unsharable_empty = { { Q_BASIC_ATOMIC_INITIALIZER(0) }, 0, 0, 0, 0 }; QArrayData *QArrayData::allocate(size_t objectSize, size_t alignment, - size_t capacity, bool reserve) + size_t capacity, bool reserve, bool sharable) { // Alignment is a power of two Q_ASSERT(alignment >= Q_ALIGNOF(QArrayData) @@ -55,7 +56,9 @@ QArrayData *QArrayData::allocate(size_t objectSize, size_t alignment, // Don't allocate empty headers if (!capacity) - return const_cast<QArrayData *>(&shared_empty); + return sharable + ? const_cast<QArrayData *>(&shared_empty) + : const_cast<QArrayData *>(&unsharable_empty); // Allocate extra (alignment - Q_ALIGNOF(QArrayData)) padding bytes so we // can properly align the data array. This assumes malloc is able to @@ -69,7 +72,7 @@ QArrayData *QArrayData::allocate(size_t objectSize, size_t alignment, quintptr data = (quintptr(header) + sizeof(QArrayData) + alignment - 1) & ~(alignment - 1); - header->ref.initializeOwned(); + header->ref.atomic.store(sharable ? 1 : 0); header->size = 0; header->alloc = capacity; header->capacityReserved = reserve; @@ -87,6 +90,9 @@ void QArrayData::deallocate(QArrayData *data, size_t objectSize, && !(alignment & (alignment - 1))); Q_UNUSED(objectSize) Q_UNUSED(alignment) + if (data == &unsharable_empty) + return; + qFree(data); } diff --git a/src/corelib/tools/qarraydata.h b/src/corelib/tools/qarraydata.h index b7ab59257f..1fd60e2155 100644 --- a/src/corelib/tools/qarraydata.h +++ b/src/corelib/tools/qarraydata.h @@ -74,12 +74,13 @@ struct Q_CORE_EXPORT QArrayData } static QArrayData *allocate(size_t objectSize, size_t alignment, - size_t capacity, bool reserve) Q_REQUIRED_RESULT; + size_t capacity, bool reserve, bool sharable) Q_REQUIRED_RESULT; static void deallocate(QArrayData *data, size_t objectSize, size_t alignment); static const QArrayData shared_null; static const QArrayData shared_empty; + static const QArrayData unsharable_empty; }; template <class T> @@ -99,11 +100,11 @@ struct QTypedArrayData class AlignmentDummy { QArrayData header; T data; }; - static QTypedArrayData *allocate(size_t capacity, bool reserve = false) - Q_REQUIRED_RESULT + static QTypedArrayData *allocate(size_t capacity, bool reserve = false, + bool sharable = true) Q_REQUIRED_RESULT { return static_cast<QTypedArrayData *>(QArrayData::allocate(sizeof(T), - Q_ALIGNOF(AlignmentDummy), capacity, reserve)); + Q_ALIGNOF(AlignmentDummy), capacity, reserve, sharable)); } static void deallocate(QArrayData *data) @@ -122,6 +123,12 @@ struct QTypedArrayData return static_cast<QTypedArrayData *>( const_cast<QArrayData *>(&QArrayData::shared_empty)); } + + static QTypedArrayData *unsharableEmpty() + { + return static_cast<QTypedArrayData *>( + const_cast<QArrayData *>(&QArrayData::unsharable_empty)); + } }; template <class T, size_t N> diff --git a/src/corelib/tools/qarraydataops.h b/src/corelib/tools/qarraydataops.h index e7c66a456b..a3c372fe6b 100644 --- a/src/corelib/tools/qarraydataops.h +++ b/src/corelib/tools/qarraydataops.h @@ -61,7 +61,7 @@ struct QPodArrayOps { void copyAppend(const T *b, const T *e) { - Q_ASSERT(this->ref == 1); + Q_ASSERT(!this->ref.isShared()); Q_ASSERT(b < e); Q_ASSERT(size_t(e - b) <= this->alloc - uint(this->size)); @@ -71,7 +71,7 @@ struct QPodArrayOps void copyAppend(size_t n, const T &t) { - Q_ASSERT(this->ref == 1); + Q_ASSERT(!this->ref.isShared()); Q_ASSERT(n <= this->alloc - uint(this->size)); T *iter = this->end(); @@ -91,7 +91,7 @@ struct QPodArrayOps void insert(T *where, const T *b, const T *e) { - Q_ASSERT(this->ref == 1); + Q_ASSERT(!this->ref.isShared()); Q_ASSERT(where >= this->begin() && where < this->end()); // Use copyAppend at end Q_ASSERT(b < e); Q_ASSERT(e <= where || b > this->end()); // No overlap @@ -109,7 +109,7 @@ struct QGenericArrayOps { void copyAppend(const T *b, const T *e) { - Q_ASSERT(this->ref == 1); + Q_ASSERT(!this->ref.isShared()); Q_ASSERT(b < e); Q_ASSERT(size_t(e - b) <= this->alloc - uint(this->size)); @@ -122,7 +122,7 @@ struct QGenericArrayOps void copyAppend(size_t n, const T &t) { - Q_ASSERT(this->ref == 1); + Q_ASSERT(!this->ref.isShared()); Q_ASSERT(n <= this->alloc - uint(this->size)); T *iter = this->end(); @@ -149,7 +149,7 @@ struct QGenericArrayOps void insert(T *where, const T *b, const T *e) { - Q_ASSERT(this->ref == 1); + Q_ASSERT(!this->ref.isShared()); Q_ASSERT(where >= this->begin() && where < this->end()); // Use copyAppend at end Q_ASSERT(b < e); Q_ASSERT(e <= where || b > this->end()); // No overlap @@ -222,7 +222,7 @@ struct QMovableArrayOps void insert(T *where, const T *b, const T *e) { - Q_ASSERT(this->ref == 1); + Q_ASSERT(!this->ref.isShared()); Q_ASSERT(where >= this->begin() && where < this->end()); // Use copyAppend at end Q_ASSERT(b < e); Q_ASSERT(e <= where || b > this->end()); // No overlap diff --git a/src/corelib/tools/qarraydatapointer.h b/src/corelib/tools/qarraydatapointer.h index f1cd1dc4b1..e42d146c58 100644 --- a/src/corelib/tools/qarraydatapointer.h +++ b/src/corelib/tools/qarraydatapointer.h @@ -64,7 +64,9 @@ public: } QArrayDataPointer(const QArrayDataPointer &other) - : d((other.d->ref.ref(), other.d)) + : d(other.d->ref.ref() + ? other.d + : other.clone()) { } @@ -110,6 +112,22 @@ public: return d; } + void setSharable(bool sharable) + { + if (d->alloc == 0 && d->size == 0) { + Q_ASSERT(Data::sharedNull() == d + || Data::sharedEmpty() == d + || Data::unsharableEmpty() == d); + d = sharable + ? Data::sharedEmpty() + : Data::unsharableEmpty(); + return; + } + + detach(); + d->ref.setSharable(sharable); + } + void swap(QArrayDataPointer &other) { qSwap(d, other.d); diff --git a/src/corelib/tools/qrefcount.h b/src/corelib/tools/qrefcount.h index 9478ff1269..bf864f2f58 100644 --- a/src/corelib/tools/qrefcount.h +++ b/src/corelib/tools/qrefcount.h @@ -111,6 +111,7 @@ public: { return atomic.load(); } void initializeOwned() { atomic.store(1); } + void initializeUnsharable() { atomic.store(0); } QBasicAtomicInt atomic; }; |