summaryrefslogtreecommitdiffstats
path: root/src/corelib
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib')
-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;
};