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
|
||||
: 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)
|
||||
{
|
||||
Q_ASSERT(!this->ref.isShared());
|
||||
@ -105,6 +115,18 @@ template <class T>
|
||||
struct QGenericArrayOps
|
||||
: 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)
|
||||
{
|
||||
Q_ASSERT(!this->ref.isShared());
|
||||
@ -215,6 +237,7 @@ template <class T>
|
||||
struct QMovableArrayOps
|
||||
: QGenericArrayOps<T>
|
||||
{
|
||||
// using QGenericArrayOps<T>::appendInitialize;
|
||||
// using QGenericArrayOps<T>::copyAppend;
|
||||
// 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)
|
||||
: d(Data::allocate(n))
|
||||
{
|
||||
|
@ -81,6 +81,7 @@ private slots:
|
||||
void typedData();
|
||||
void gccBug43247();
|
||||
void arrayOps();
|
||||
void appendInitialize();
|
||||
void setSharable_data();
|
||||
void setSharable();
|
||||
void fromRawData();
|
||||
@ -894,11 +895,15 @@ struct CountedObject
|
||||
{
|
||||
CountedObject()
|
||||
: id(liveCount++)
|
||||
, flags(DefaultConstructed)
|
||||
{
|
||||
}
|
||||
|
||||
CountedObject(const CountedObject &other)
|
||||
: id(other.id)
|
||||
, flags(other.flags == DefaultConstructed
|
||||
? ObjectFlags(CopyConstructed | DefaultConstructed)
|
||||
: CopyConstructed)
|
||||
{
|
||||
++liveCount;
|
||||
}
|
||||
@ -910,6 +915,7 @@ struct CountedObject
|
||||
|
||||
CountedObject &operator=(const CountedObject &other)
|
||||
{
|
||||
flags = ObjectFlags(other.flags | CopyAssigned);
|
||||
id = other.id;
|
||||
return *this;
|
||||
}
|
||||
@ -930,7 +936,15 @@ struct CountedObject
|
||||
const size_t previousLiveCount;
|
||||
};
|
||||
|
||||
enum ObjectFlags {
|
||||
DefaultConstructed = 1,
|
||||
CopyConstructed = 2,
|
||||
CopyAssigned = 4
|
||||
};
|
||||
|
||||
size_t id; // not unique
|
||||
ObjectFlags flags;
|
||||
|
||||
static size_t liveCount;
|
||||
};
|
||||
|
||||
@ -968,7 +982,10 @@ void tst_QArrayData::arrayOps()
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
QCOMPARE(vi[i], intArray[i]);
|
||||
QVERIFY(vs[i].isSharedWith(stringArray[i]));
|
||||
|
||||
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) {
|
||||
QCOMPARE(vi[i], referenceInt);
|
||||
QVERIFY(vs[i].isSharedWith(referenceString));
|
||||
|
||||
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(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]);
|
||||
QVERIFY(vs[i].isSharedWith(stringArray[i % 5]));
|
||||
|
||||
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) {
|
||||
QCOMPARE(vi[i], referenceInt);
|
||||
QVERIFY(vs[i].isSharedWith(referenceString));
|
||||
|
||||
QCOMPARE(vo[i].id, referenceObject.id);
|
||||
QCOMPARE(int(vo[i].flags), CountedObject::CopyConstructed
|
||||
| CountedObject::CopyAssigned);
|
||||
}
|
||||
|
||||
for (int i = 20; i < 25; ++i) {
|
||||
QCOMPARE(vi[i], intArray[i % 5]);
|
||||
QVERIFY(vs[i].isSharedWith(stringArray[i % 5]));
|
||||
|
||||
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) {
|
||||
QCOMPARE(vi[i], referenceInt);
|
||||
QVERIFY(vs[i].isSharedWith(referenceString));
|
||||
|
||||
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