Introduce QArrayDataOps::appendInitialize
Adds given number of default-initialized elements at end of array. For POD types, initialization is reduced to a single memset call. Other types get default constructed in place. As part of adding a test for the new functionality the arrayOps test was extended to verify objects are being constructed and assigned as desired. Change-Id: I9fb2afe0d92667e76993313fcd370fe129d72b90 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
parent
e4682cc880
commit
646dc6c5da
@ -57,6 +57,16 @@ template <class T>
|
|||||||
struct QPodArrayOps
|
struct QPodArrayOps
|
||||||
: QTypedArrayData<T>
|
: QTypedArrayData<T>
|
||||||
{
|
{
|
||||||
|
void appendInitialize(size_t newSize)
|
||||||
|
{
|
||||||
|
Q_ASSERT(!this->ref.isShared());
|
||||||
|
Q_ASSERT(newSize > uint(this->size));
|
||||||
|
Q_ASSERT(newSize <= this->alloc);
|
||||||
|
|
||||||
|
::memset(this->end(), 0, (newSize - this->size) * sizeof(T));
|
||||||
|
this->size = newSize;
|
||||||
|
}
|
||||||
|
|
||||||
void copyAppend(const T *b, const T *e)
|
void copyAppend(const T *b, const T *e)
|
||||||
{
|
{
|
||||||
Q_ASSERT(!this->ref.isShared());
|
Q_ASSERT(!this->ref.isShared());
|
||||||
@ -105,6 +115,18 @@ template <class T>
|
|||||||
struct QGenericArrayOps
|
struct QGenericArrayOps
|
||||||
: QTypedArrayData<T>
|
: QTypedArrayData<T>
|
||||||
{
|
{
|
||||||
|
void appendInitialize(size_t newSize)
|
||||||
|
{
|
||||||
|
Q_ASSERT(!this->ref.isShared());
|
||||||
|
Q_ASSERT(newSize > uint(this->size));
|
||||||
|
Q_ASSERT(newSize <= this->alloc);
|
||||||
|
|
||||||
|
T *const begin = this->begin();
|
||||||
|
do {
|
||||||
|
new (begin + this->size) T();
|
||||||
|
} while (uint(++this->size) != newSize);
|
||||||
|
}
|
||||||
|
|
||||||
void copyAppend(const T *b, const T *e)
|
void copyAppend(const T *b, const T *e)
|
||||||
{
|
{
|
||||||
Q_ASSERT(!this->ref.isShared());
|
Q_ASSERT(!this->ref.isShared());
|
||||||
@ -215,6 +237,7 @@ template <class T>
|
|||||||
struct QMovableArrayOps
|
struct QMovableArrayOps
|
||||||
: QGenericArrayOps<T>
|
: QGenericArrayOps<T>
|
||||||
{
|
{
|
||||||
|
// using QGenericArrayOps<T>::appendInitialize;
|
||||||
// using QGenericArrayOps<T>::copyAppend;
|
// using QGenericArrayOps<T>::copyAppend;
|
||||||
// using QGenericArrayOps<T>::destroyAll;
|
// using QGenericArrayOps<T>::destroyAll;
|
||||||
|
|
||||||
|
@ -63,6 +63,13 @@ public:
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
explicit SimpleVector(size_t n)
|
||||||
|
: d(Data::allocate(n))
|
||||||
|
{
|
||||||
|
if (n)
|
||||||
|
d->appendInitialize(n);
|
||||||
|
}
|
||||||
|
|
||||||
SimpleVector(size_t n, const T &t)
|
SimpleVector(size_t n, const T &t)
|
||||||
: d(Data::allocate(n))
|
: d(Data::allocate(n))
|
||||||
{
|
{
|
||||||
|
@ -81,6 +81,7 @@ private slots:
|
|||||||
void typedData();
|
void typedData();
|
||||||
void gccBug43247();
|
void gccBug43247();
|
||||||
void arrayOps();
|
void arrayOps();
|
||||||
|
void appendInitialize();
|
||||||
void setSharable_data();
|
void setSharable_data();
|
||||||
void setSharable();
|
void setSharable();
|
||||||
void fromRawData();
|
void fromRawData();
|
||||||
@ -894,11 +895,15 @@ struct CountedObject
|
|||||||
{
|
{
|
||||||
CountedObject()
|
CountedObject()
|
||||||
: id(liveCount++)
|
: id(liveCount++)
|
||||||
|
, flags(DefaultConstructed)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
CountedObject(const CountedObject &other)
|
CountedObject(const CountedObject &other)
|
||||||
: id(other.id)
|
: id(other.id)
|
||||||
|
, flags(other.flags == DefaultConstructed
|
||||||
|
? ObjectFlags(CopyConstructed | DefaultConstructed)
|
||||||
|
: CopyConstructed)
|
||||||
{
|
{
|
||||||
++liveCount;
|
++liveCount;
|
||||||
}
|
}
|
||||||
@ -910,6 +915,7 @@ struct CountedObject
|
|||||||
|
|
||||||
CountedObject &operator=(const CountedObject &other)
|
CountedObject &operator=(const CountedObject &other)
|
||||||
{
|
{
|
||||||
|
flags = ObjectFlags(other.flags | CopyAssigned);
|
||||||
id = other.id;
|
id = other.id;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@ -930,7 +936,15 @@ struct CountedObject
|
|||||||
const size_t previousLiveCount;
|
const size_t previousLiveCount;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum ObjectFlags {
|
||||||
|
DefaultConstructed = 1,
|
||||||
|
CopyConstructed = 2,
|
||||||
|
CopyAssigned = 4
|
||||||
|
};
|
||||||
|
|
||||||
size_t id; // not unique
|
size_t id; // not unique
|
||||||
|
ObjectFlags flags;
|
||||||
|
|
||||||
static size_t liveCount;
|
static size_t liveCount;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -968,7 +982,10 @@ void tst_QArrayData::arrayOps()
|
|||||||
for (int i = 0; i < 5; ++i) {
|
for (int i = 0; i < 5; ++i) {
|
||||||
QCOMPARE(vi[i], intArray[i]);
|
QCOMPARE(vi[i], intArray[i]);
|
||||||
QVERIFY(vs[i].isSharedWith(stringArray[i]));
|
QVERIFY(vs[i].isSharedWith(stringArray[i]));
|
||||||
|
|
||||||
QCOMPARE(vo[i].id, objArray[i].id);
|
QCOMPARE(vo[i].id, objArray[i].id);
|
||||||
|
QCOMPARE(int(vo[i].flags), CountedObject::CopyConstructed
|
||||||
|
| CountedObject::DefaultConstructed);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
@ -997,7 +1014,10 @@ void tst_QArrayData::arrayOps()
|
|||||||
for (int i = 0; i < 5; ++i) {
|
for (int i = 0; i < 5; ++i) {
|
||||||
QCOMPARE(vi[i], referenceInt);
|
QCOMPARE(vi[i], referenceInt);
|
||||||
QVERIFY(vs[i].isSharedWith(referenceString));
|
QVERIFY(vs[i].isSharedWith(referenceString));
|
||||||
|
|
||||||
QCOMPARE(vo[i].id, referenceObject.id);
|
QCOMPARE(vo[i].id, referenceObject.id);
|
||||||
|
QCOMPARE(int(vo[i].flags), CountedObject::CopyConstructed
|
||||||
|
| CountedObject::DefaultConstructed);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
@ -1042,28 +1062,80 @@ void tst_QArrayData::arrayOps()
|
|||||||
QCOMPARE(vo.size(), size_t(30));
|
QCOMPARE(vo.size(), size_t(30));
|
||||||
|
|
||||||
QCOMPARE(CountedObject::liveCount, size_t(36));
|
QCOMPARE(CountedObject::liveCount, size_t(36));
|
||||||
for (int i = 0; i < 15; ++i) {
|
for (int i = 0; i < 5; ++i) {
|
||||||
QCOMPARE(vi[i], intArray[i % 5]);
|
QCOMPARE(vi[i], intArray[i % 5]);
|
||||||
QVERIFY(vs[i].isSharedWith(stringArray[i % 5]));
|
QVERIFY(vs[i].isSharedWith(stringArray[i % 5]));
|
||||||
|
|
||||||
QCOMPARE(vo[i].id, objArray[i % 5].id);
|
QCOMPARE(vo[i].id, objArray[i % 5].id);
|
||||||
|
QCOMPARE(int(vo[i].flags), CountedObject::DefaultConstructed
|
||||||
|
| CountedObject::CopyAssigned);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 5; i < 15; ++i) {
|
||||||
|
QCOMPARE(vi[i], intArray[i % 5]);
|
||||||
|
QVERIFY(vs[i].isSharedWith(stringArray[i % 5]));
|
||||||
|
|
||||||
|
QCOMPARE(vo[i].id, objArray[i % 5].id);
|
||||||
|
QCOMPARE(int(vo[i].flags), CountedObject::CopyConstructed
|
||||||
|
| CountedObject::CopyAssigned);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 15; i < 20; ++i) {
|
for (int i = 15; i < 20; ++i) {
|
||||||
QCOMPARE(vi[i], referenceInt);
|
QCOMPARE(vi[i], referenceInt);
|
||||||
QVERIFY(vs[i].isSharedWith(referenceString));
|
QVERIFY(vs[i].isSharedWith(referenceString));
|
||||||
|
|
||||||
QCOMPARE(vo[i].id, referenceObject.id);
|
QCOMPARE(vo[i].id, referenceObject.id);
|
||||||
|
QCOMPARE(int(vo[i].flags), CountedObject::CopyConstructed
|
||||||
|
| CountedObject::CopyAssigned);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 20; i < 25; ++i) {
|
for (int i = 20; i < 25; ++i) {
|
||||||
QCOMPARE(vi[i], intArray[i % 5]);
|
QCOMPARE(vi[i], intArray[i % 5]);
|
||||||
QVERIFY(vs[i].isSharedWith(stringArray[i % 5]));
|
QVERIFY(vs[i].isSharedWith(stringArray[i % 5]));
|
||||||
|
|
||||||
QCOMPARE(vo[i].id, objArray[i % 5].id);
|
QCOMPARE(vo[i].id, objArray[i % 5].id);
|
||||||
|
|
||||||
|
// Originally inserted as (DefaultConstructed | CopyAssigned), later
|
||||||
|
// get shuffled into place by std::rotate (SimpleVector::insert,
|
||||||
|
// overlapping mode).
|
||||||
|
// Depending on implementation of rotate, final assignment can be:
|
||||||
|
// - straight from source: DefaultConstructed | CopyAssigned
|
||||||
|
// - through a temporary: CopyConstructed | CopyAssigned
|
||||||
|
QCOMPARE(vo[i].flags & CountedObject::CopyAssigned,
|
||||||
|
int(CountedObject::CopyAssigned));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 25; i < 30; ++i) {
|
for (int i = 25; i < 30; ++i) {
|
||||||
QCOMPARE(vi[i], referenceInt);
|
QCOMPARE(vi[i], referenceInt);
|
||||||
QVERIFY(vs[i].isSharedWith(referenceString));
|
QVERIFY(vs[i].isSharedWith(referenceString));
|
||||||
|
|
||||||
QCOMPARE(vo[i].id, referenceObject.id);
|
QCOMPARE(vo[i].id, referenceObject.id);
|
||||||
|
QCOMPARE(int(vo[i].flags), CountedObject::CopyConstructed
|
||||||
|
| CountedObject::CopyAssigned);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_QArrayData::appendInitialize()
|
||||||
|
{
|
||||||
|
CountedObject::LeakChecker leakChecker; Q_UNUSED(leakChecker)
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
// appendInitialize
|
||||||
|
SimpleVector<int> vi(5);
|
||||||
|
SimpleVector<QString> vs(5);
|
||||||
|
SimpleVector<CountedObject> vo(5);
|
||||||
|
|
||||||
|
QCOMPARE(vi.size(), size_t(5));
|
||||||
|
QCOMPARE(vs.size(), size_t(5));
|
||||||
|
QCOMPARE(vo.size(), size_t(5));
|
||||||
|
|
||||||
|
QCOMPARE(CountedObject::liveCount, size_t(5));
|
||||||
|
for (size_t i = 0; i < 5; ++i) {
|
||||||
|
QCOMPARE(vi[i], 0);
|
||||||
|
QVERIFY(vs[i].isNull());
|
||||||
|
|
||||||
|
QCOMPARE(vo[i].id, i);
|
||||||
|
QCOMPARE(int(vo[i].flags), int(CountedObject::DefaultConstructed));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user