src/corelib/tools/qcontiguouscache.h
changeset 3 41300fa6a67c
parent 0 1918ee327afb
child 4 3b1da2848fc7
--- a/src/corelib/tools/qcontiguouscache.h	Tue Jan 26 12:42:25 2010 +0200
+++ b/src/corelib/tools/qcontiguouscache.h	Tue Feb 02 00:43:10 2010 +0200
@@ -62,6 +62,15 @@
     int start;
     int offset;
     uint sharable : 1;
+    uint reserved : 31;
+
+    // total is 24 bytes (HP-UX aCC: 40 bytes)
+    // the next entry is already aligned to 8 bytes
+    // there will be an 8 byte gap here if T requires 16-byte alignment
+    //  (such as long double on 64-bit platforms, __int128, __float128)
+
+    static QContiguousCacheData *allocate(int size, int alignment);
+    static void free(QContiguousCacheData *data);
 
 #ifdef QT_QCONTIGUOUSCACHE_DEBUG
     void dump() const;
@@ -69,33 +78,32 @@
 };
 
 template <typename T>
-struct QContiguousCacheTypedData
+struct QContiguousCacheTypedData: private QContiguousCacheData
 {
-    QBasicAtomicInt ref;
-    int alloc;
-    int count;
-    int start;
-    int offset;
-    uint sharable : 1;
-    // uint unused : 31;
+    // private inheritance to avoid aliasing warningss
+    T array[1];
 
-    // total is 24 bytes (HP-UX aCC: 40 bytes)
-    // the next entry is already aligned to 8 bytes
-    // there will be an 8 byte gap here if T requires 16-byte alignment
-    //  (such as long double on 64-bit platforms, __int128, __float128)
-
-    T array[1];
+    static inline void free(QContiguousCacheTypedData *data) { QContiguousCacheData::free(data); }
 };
 
 template<typename T>
 class QContiguousCache {
     typedef QContiguousCacheTypedData<T> Data;
-    union { QContiguousCacheData *p; QContiguousCacheTypedData<T> *d; };
+    union { QContiguousCacheData *d; QContiguousCacheTypedData<T> *p; };
 public:
+    // STL compatibility
+    typedef T value_type;
+    typedef value_type* pointer;
+    typedef const value_type* const_pointer;
+    typedef value_type& reference;
+    typedef const value_type& const_reference;
+    typedef ptrdiff_t difference_type;
+    typedef int size_type;
+
     explicit QContiguousCache(int capacity = 0);
     QContiguousCache(const QContiguousCache<T> &v) : d(v.d) { d->ref.ref(); if (!d->sharable) detach_helper(); }
 
-    inline ~QContiguousCache() { if (!d) return; if (!d->ref.deref()) free(d); }
+    inline ~QContiguousCache() { if (!d) return; if (!d->ref.deref()) free(p); }
 
     inline void detach() { if (d->ref != 1) detach_helper(); }
     inline bool isDetached() const { return d->ref == 1; }
@@ -128,10 +136,10 @@
     inline int firstIndex() const { return d->offset; }
     inline int lastIndex() const { return d->offset + d->count - 1; }
 
-    inline const T &first() const { Q_ASSERT(!isEmpty()); return d->array[d->start]; }
-    inline const T &last() const { Q_ASSERT(!isEmpty()); return d->array[(d->start + d->count -1) % d->alloc]; }
-    inline T &first() { Q_ASSERT(!isEmpty()); detach(); return d->array[d->start]; }
-    inline T &last() { Q_ASSERT(!isEmpty()); detach(); return d->array[(d->start + d->count -1) % d->alloc]; }
+    inline const T &first() const { Q_ASSERT(!isEmpty()); return p->array[d->start]; }
+    inline const T &last() const { Q_ASSERT(!isEmpty()); return p->array[(d->start + d->count -1) % d->alloc]; }
+    inline T &first() { Q_ASSERT(!isEmpty()); detach(); return p->array[d->start]; }
+    inline T &last() { Q_ASSERT(!isEmpty()); detach(); return p->array[(d->start + d->count -1) % d->alloc]; }
 
     void removeFirst();
     T takeFirst();
@@ -156,23 +164,32 @@
         // count the padding at the end
         return reinterpret_cast<const char *>(&(reinterpret_cast<const Data *>(this))->array[1]) - reinterpret_cast<const char *>(this);
     }
+    int alignOfTypedData() const
+    {
+#ifdef Q_ALIGNOF
+        return qMax<int>(sizeof(void*), Q_ALIGNOF(Data));
+#else
+        return 0;
+#endif
+    }
 };
 
 template <typename T>
 void QContiguousCache<T>::detach_helper()
 {
-    union { QContiguousCacheData *p; QContiguousCacheTypedData<T> *d; } x;
+    union { QContiguousCacheData *d; QContiguousCacheTypedData<T> *p; } x;
 
-    x.p = malloc(d->alloc);
+    x.d = malloc(d->alloc);
     x.d->ref = 1;
     x.d->count = d->count;
     x.d->start = d->start;
     x.d->offset = d->offset;
     x.d->alloc = d->alloc;
     x.d->sharable = true;
+    x.d->reserved = 0;
 
-    T *dest = x.d->array + x.d->start;
-    T *src = d->array + d->start;
+    T *dest = x.p->array + x.d->start;
+    T *src = p->array + d->start;
     int oldcount = x.d->count;
     while (oldcount--) {
         if (QTypeInfo<T>::isComplex) {
@@ -181,15 +198,15 @@
             *dest = *src;
         }
         dest++;
-        if (dest == x.d->array + x.d->alloc)
-            dest = x.d->array;
+        if (dest == x.p->array + x.d->alloc)
+            dest = x.p->array;
         src++;
-        if (src == d->array + d->alloc)
-            src = d->array;
+        if (src == p->array + d->alloc)
+            src = p->array;
     }
 
     if (!d->ref.deref())
-        free(d);
+        free(p);
     d = x.d;
 }
 
@@ -199,14 +216,14 @@
     if (asize == d->alloc)
         return;
     detach();
-    union { QContiguousCacheData *p; QContiguousCacheTypedData<T> *d; } x;
-    x.p = malloc(asize);
+    union { QContiguousCacheData *d; QContiguousCacheTypedData<T> *p; } x;
+    x.d = malloc(asize);
     x.d->alloc = asize;
     x.d->count = qMin(d->count, asize);
     x.d->offset = d->offset + d->count - x.d->count;
     x.d->start = x.d->offset % x.d->alloc;
-    T *dest = x.d->array + (x.d->start + x.d->count-1) % x.d->alloc;
-    T *src = d->array + (d->start + d->count-1) % d->alloc;
+    T *dest = x.p->array + (x.d->start + x.d->count-1) % x.d->alloc;
+    T *src = p->array + (d->start + d->count-1) % d->alloc;
     int oldcount = x.d->count;
     while (oldcount--) {
         if (QTypeInfo<T>::isComplex) {
@@ -214,15 +231,15 @@
         } else {
             *dest = *src;
         }
-        if (dest == x.d->array)
-            dest = x.d->array + x.d->alloc;
+        if (dest == x.p->array)
+            dest = x.p->array + x.d->alloc;
         dest--;
-        if (src == d->array)
-            src = d->array + d->alloc;
+        if (src == p->array)
+            src = p->array + d->alloc;
         src--;
     }
     /* free old */
-    free(d);
+    free(p);
     d = x.d;
 }
 
@@ -232,24 +249,24 @@
     if (d->ref == 1) {
         if (QTypeInfo<T>::isComplex) {
             int oldcount = d->count;
-            T * i = d->array + d->start;
-            T * e = d->array + d->alloc;
+            T * i = p->array + d->start;
+            T * e = p->array + d->alloc;
             while (oldcount--) {
                 i->~T();
                 i++;
                 if (i == e)
-                    i = d->array;
+                    i = p->array;
             }
         }
         d->count = d->start = d->offset = 0;
     } else {
-        union { QContiguousCacheData *p; QContiguousCacheTypedData<T> *d; } x;
-        x.p = malloc(d->alloc);
+        union { QContiguousCacheData *d; QContiguousCacheTypedData<T> *p; } x;
+        x.d = malloc(d->alloc);
         x.d->ref = 1;
         x.d->alloc = d->alloc;
         x.d->count = x.d->start = x.d->offset = 0;
         x.d->sharable = true;
-        if (!d->ref.deref()) free(d);
+        if (!d->ref.deref()) free(p);
         d = x.d;
     }
 }
@@ -257,13 +274,13 @@
 template <typename T>
 inline QContiguousCacheData *QContiguousCache<T>::malloc(int aalloc)
 {
-    return static_cast<QContiguousCacheData *>(qMalloc(sizeOfTypedData() + (aalloc - 1) * sizeof(T)));
+    return QContiguousCacheData::allocate(sizeOfTypedData() + (aalloc - 1) * sizeof(T), alignOfTypedData());
 }
 
 template <typename T>
 QContiguousCache<T>::QContiguousCache(int cap)
 {
-    p = malloc(cap);
+    d = malloc(cap);
     d->ref = 1;
     d->alloc = cap;
     d->count = d->start = d->offset = 0;
@@ -303,16 +320,16 @@
 {
     if (QTypeInfo<T>::isComplex) {
         int oldcount = d->count;
-        T * i = d->array + d->start;
-        T * e = d->array + d->alloc;
+        T * i = p->array + d->start;
+        T * e = p->array + d->alloc;
         while (oldcount--) {
             i->~T();
             i++;
             if (i == e)
-                i = d->array;
+                i = p->array;
         }
     }
-    qFree(x);
+    x->free(x);
 }
 template <typename T>
 void QContiguousCache<T>::append(const T &value)
@@ -320,10 +337,10 @@
     detach();
     if (QTypeInfo<T>::isComplex) {
         if (d->count == d->alloc)
-            (d->array + (d->start+d->count) % d->alloc)->~T();
-        new (d->array + (d->start+d->count) % d->alloc) T(value);
+            (p->array + (d->start+d->count) % d->alloc)->~T();
+        new (p->array + (d->start+d->count) % d->alloc) T(value);
     } else {
-        d->array[(d->start+d->count) % d->alloc] = value;
+        p->array[(d->start+d->count) % d->alloc] = value;
     }
 
     if (d->count == d->alloc) {
@@ -349,12 +366,12 @@
         d->count++;
     else
         if (d->count == d->alloc)
-            (d->array + d->start)->~T();
+            (p->array + d->start)->~T();
 
     if (QTypeInfo<T>::isComplex)
-        new (d->array + d->start) T(value);
+        new (p->array + d->start) T(value);
     else
-        d->array[d->start] = value;
+        p->array[d->start] = value;
 }
 
 template<typename T>
@@ -364,9 +381,9 @@
     detach();
     if (containsIndex(pos)) {
         if(QTypeInfo<T>::isComplex)
-            new (d->array + pos % d->alloc) T(value);
+            new (p->array + pos % d->alloc) T(value);
         else
-            d->array[pos % d->alloc] = value;
+            p->array[pos % d->alloc] = value;
     } else if (pos == d->offset-1)
         prepend(value);
     else if (pos == d->offset+d->count)
@@ -378,18 +395,18 @@
         d->start = pos % d->alloc;
         d->count = 1;
         if (QTypeInfo<T>::isComplex)
-            new (d->array + d->start) T(value);
+            new (p->array + d->start) T(value);
         else
-            d->array[d->start] = value;
+            p->array[d->start] = value;
     }
 }
 
 template <typename T>
 inline const T &QContiguousCache<T>::at(int pos) const
-{ Q_ASSERT_X(pos >= d->offset && pos - d->offset < d->count, "QContiguousCache<T>::at", "index out of range"); return d->array[pos % d->alloc]; }
+{ Q_ASSERT_X(pos >= d->offset && pos - d->offset < d->count, "QContiguousCache<T>::at", "index out of range"); return p->array[pos % d->alloc]; }
 template <typename T>
 inline const T &QContiguousCache<T>::operator[](int pos) const
-{ Q_ASSERT_X(pos >= d->offset && pos - d->offset < d->count, "QContiguousCache<T>::at", "index out of range"); return d->array[pos % d->alloc]; }
+{ Q_ASSERT_X(pos >= d->offset && pos - d->offset < d->count, "QContiguousCache<T>::at", "index out of range"); return p->array[pos % d->alloc]; }
 
 template <typename T>
 inline T &QContiguousCache<T>::operator[](int pos)
@@ -397,7 +414,7 @@
     detach();
     if (!containsIndex(pos))
         insert(pos, T());
-    return d->array[pos % d->alloc];
+    return p->array[pos % d->alloc];
 }
 
 template <typename T>
@@ -407,7 +424,7 @@
     detach();
     d->count--;
     if (QTypeInfo<T>::isComplex)
-        (d->array + d->start)->~T();
+        (p->array + d->start)->~T();
     d->start = (d->start + 1) % d->alloc;
     d->offset++;
 }
@@ -419,7 +436,7 @@
     detach();
     d->count--;
     if (QTypeInfo<T>::isComplex)
-        (d->array + (d->start + d->count) % d->alloc)->~T();
+        (p->array + (d->start + d->count) % d->alloc)->~T();
 }
 
 template <typename T>