summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJoão Abecasis <joao.abecasis@nokia.com>2011-11-24 17:15:11 +0100
committerQt by Nokia <qt-info@nokia.com>2012-01-06 17:25:09 +0100
commit3d61c5ca8f00b489435d5bea776b4a4c97c39793 (patch)
tree45480cd94b6dbb0899398c0abb692bc1ebba3aca /src
parent51048e1f31df5be45e71a75fc535111dd36c4c9e (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.cpp12
-rw-r--r--src/corelib/tools/qarraydata.h15
-rw-r--r--src/corelib/tools/qarraydataops.h14
-rw-r--r--src/corelib/tools/qarraydatapointer.h20
-rw-r--r--src/corelib/tools/qrefcount.h1
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;
};