Use RefCount::setSharable feature in QVector

Note: This constitutes a break in Binary Compatibility.

Change-Id: I050587901725b701f20dd46475ae48aec28aa54d
Reviewed-by: Bradley T. Hughes <bradley.hughes@nokia.com>
This commit is contained in:
João Abecasis 2011-10-31 15:30:20 +01:00 committed by Qt by Nokia
parent f1e48d48fd
commit cb0cdf6c08
3 changed files with 37 additions and 26 deletions

View File

@ -52,7 +52,7 @@ static inline int alignmentThreshold()
return 2 * sizeof(void*);
}
const QVectorData QVectorData::shared_null = { Q_REFCOUNT_INITIALIZE_STATIC, 0, 0, true, false, 0 };
const QVectorData QVectorData::shared_null = { Q_REFCOUNT_INITIALIZE_STATIC, 0, 0, false, 0 };
QVectorData *QVectorData::malloc(int sizeofTypedData, int size, int sizeofT, QVectorData *init)
{

View File

@ -70,13 +70,11 @@ struct Q_CORE_EXPORT QVectorData
int size;
#if defined(QT_ARCH_SPARC) && defined(Q_CC_GNU) && defined(__LP64__) && defined(QT_BOOTSTRAPPED)
// workaround for bug in gcc 3.4.2
uint sharable;
uint capacity;
uint reserved;
#else
uint sharable : 1;
uint capacity : 1;
uint reserved : 30;
uint reserved : 31;
#endif
static const QVectorData shared_null;
@ -120,7 +118,19 @@ public:
inline QVector() : d(const_cast<QVectorData *>(&QVectorData::shared_null)) { }
explicit QVector(int size);
QVector(int size, const T &t);
inline QVector(const QVector<T> &v) : d(v.d) { d->ref.ref(); if (!d->sharable) detach_helper(); }
inline QVector(const QVector<T> &v)
{
if (v.d->ref.ref()) {
d = v.d;
} else {
d = const_cast<QVectorData *>(&QVectorData::shared_null);
realloc(0, v.d->alloc);
qCopy(v.p->array, v.p->array + v.d->size, p->array);
d->size = v.d->size;
d->capacity = v.d->capacity;
}
}
inline ~QVector() { if (!d) return; if (!d->ref.deref()) free(p); }
QVector<T> &operator=(const QVector<T> &v);
#ifdef Q_COMPILER_RVALUE_REFS
@ -144,9 +154,18 @@ public:
void reserve(int size);
inline void squeeze() { realloc(d->size, d->size); d->capacity = 0; }
inline void detach() { if (d->ref != 1) detach_helper(); }
inline bool isDetached() const { return d->ref == 1; }
inline void setSharable(bool sharable) { if (!sharable) detach(); if (d != &QVectorData::shared_null) d->sharable = sharable; }
inline void detach() { if (!isDetached()) detach_helper(); }
inline bool isDetached() const { return !d->ref.isShared(); }
inline void setSharable(bool sharable)
{
if (sharable == d->ref.isSharable())
return;
if (!sharable)
detach();
if (d != &QVectorData::shared_null)
d->ref.setSharable(sharable);
}
inline bool isSharedWith(const QVector<T> &other) const { return d == other.d; }
inline T *data() { detach(); return p->array; }
@ -337,7 +356,7 @@ void QVector<T>::detach_helper()
{ realloc(d->size, d->alloc); }
template <typename T>
void QVector<T>::reserve(int asize)
{ if (asize > d->alloc) realloc(d->size, asize); if (d->ref == 1) d->capacity = 1; }
{ if (asize > d->alloc) realloc(d->size, asize); if (isDetached()) d->capacity = 1; }
template <typename T>
void QVector<T>::resize(int asize)
{ realloc(asize, (asize > d->alloc || (!d->capacity && asize < d->size && asize < (d->alloc >> 1))) ?
@ -389,13 +408,10 @@ inline void QVector<T>::replace(int i, const T &t)
template <typename T>
QVector<T> &QVector<T>::operator=(const QVector<T> &v)
{
QVectorData *o = v.d;
o->ref.ref();
if (!d->ref.deref())
free(p);
d = o;
if (!d->sharable)
detach_helper();
if (v.d != d) {
QVector<T> tmp(v);
tmp.swap(*this);
}
return *this;
}
@ -413,7 +429,6 @@ QVector<T>::QVector(int asize)
d = malloc(asize);
d->ref.initializeOwned();
d->alloc = d->size = asize;
d->sharable = true;
d->capacity = false;
if (QTypeInfo<T>::isComplex) {
T* b = p->array;
@ -431,7 +446,6 @@ QVector<T>::QVector(int asize, const T &t)
d = malloc(asize);
d->ref.initializeOwned();
d->alloc = d->size = asize;
d->sharable = true;
d->capacity = false;
T* i = p->array + d->size;
while (i != p->array)
@ -445,7 +459,6 @@ QVector<T>::QVector(std::initializer_list<T> args)
d = malloc(int(args.size()));
d->ref.initializeOwned();
d->alloc = d->size = int(args.size());
d->sharable = true;
d->capacity = false;
T* i = p->array + d->size;
auto it = args.end();
@ -477,7 +490,7 @@ void QVector<T>::realloc(int asize, int aalloc)
union { QVectorData *d; Data *p; } x;
x.d = d;
if (QTypeInfo<T>::isComplex && asize < d->size && d->ref == 1 ) {
if (QTypeInfo<T>::isComplex && asize < d->size && isDetached()) {
// call the destructor on all objects that need to be
// destroyed when shrinking
pOld = p->array + d->size;
@ -488,13 +501,13 @@ void QVector<T>::realloc(int asize, int aalloc)
}
}
if (aalloc != d->alloc || d->ref != 1) {
if (aalloc != d->alloc || !isDetached()) {
// (re)allocate memory
if (QTypeInfo<T>::isStatic) {
x.d = malloc(aalloc);
Q_CHECK_PTR(x.p);
x.d->size = 0;
} else if (d->ref != 1) {
} else if (!isDetached()) {
x.d = malloc(aalloc);
Q_CHECK_PTR(x.p);
if (QTypeInfo<T>::isComplex) {
@ -517,7 +530,6 @@ void QVector<T>::realloc(int asize, int aalloc)
}
x.d->ref.initializeOwned();
x.d->alloc = aalloc;
x.d->sharable = true;
x.d->capacity = d->capacity;
x.d->reserved = 0;
}
@ -572,7 +584,7 @@ Q_OUTOFLINE_TEMPLATE T QVector<T>::value(int i, const T &defaultValue) const
template <typename T>
void QVector<T>::append(const T &t)
{
if (d->ref != 1 || d->size + 1 > d->alloc) {
if (!isDetached() || d->size + 1 > d->alloc) {
const T copy(t);
realloc(d->size, (d->size + 1 > d->alloc) ?
QVectorData::grow(sizeOfTypedData(), d->size + 1, sizeof(T), QTypeInfo<T>::isStatic)
@ -596,7 +608,7 @@ Q_TYPENAME QVector<T>::iterator QVector<T>::insert(iterator before, size_type n,
int offset = int(before - p->array);
if (n != 0) {
const T copy(t);
if (d->ref != 1 || d->size + n > d->alloc)
if (!isDetached() || d->size + n > d->alloc)
realloc(d->size, QVectorData::grow(sizeOfTypedData(), d->size + n, sizeof(T),
QTypeInfo<T>::isStatic));
if (QTypeInfo<T>::isStatic) {

View File

@ -292,7 +292,6 @@ public:
d->ref.initializeOwned();
d->alloc = m_alloc;
d->size = m_size;
d->sharable = 0;
d->capacity = 0;
QVector<T> v;