summaryrefslogtreecommitdiffstats
path: root/tests/auto/collections
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@nokia.com>2009-10-22 19:09:24 (GMT)
committerThiago Macieira <thiago.macieira@nokia.com>2009-10-28 14:27:40 (GMT)
commite83bb2fdfc2dc899526c8157fd8b77a68cdde9da (patch)
tree50a23cf12df52705f254156072269ec4cce04a21 /tests/auto/collections
parent3f0b969772cf3056ed54349bfe6837d9de2995ea (diff)
downloadQt-e83bb2fdfc2dc899526c8157fd8b77a68cdde9da.zip
Qt-e83bb2fdfc2dc899526c8157fd8b77a68cdde9da.tar.gz
Qt-e83bb2fdfc2dc899526c8157fd8b77a68cdde9da.tar.bz2
Fix Qt containers to properly support types with strict alignments.
QContiguousCache is a new type, so there are no binary compatibility issues. QHash and QMap didn't have any public qMalloc / qFree, so the entire logic is contained in .cpp code. However, since old code will not inform us of the alignment requirements, we need to add a bit to the structure to indicate whether strict alignment is in use or not. QList doesn't require any changes. For small, movable types, they're all stored in the pointer array itself, so they're aligned. For larger types, we use new(), so types with stricter requirements should define their own operator new(). QLinkedList cannot be fixed. It uses new() on the QLinkedListNode, which contains a T type. Sorry. QVector did have public qMalloc / qFree. I've moved the calls to the inner function and made it keep the old calls if the alignment requirement is below a certain threshold. The idea is that, if it's above, no one was using QVector anyway. Reviewed-by: Bradley T. Hughes
Diffstat (limited to 'tests/auto/collections')
-rw-r--r--tests/auto/collections/tst_collections.cpp109
1 files changed, 109 insertions, 0 deletions
diff --git a/tests/auto/collections/tst_collections.cpp b/tests/auto/collections/tst_collections.cpp
index 670cff0..f97805e 100644
--- a/tests/auto/collections/tst_collections.cpp
+++ b/tests/auto/collections/tst_collections.cpp
@@ -164,6 +164,7 @@ private slots:
void qtimerList();
void containerTypedefs();
void forwardDeclared();
+ void alignment();
};
struct LargeStatic {
@@ -3481,5 +3482,113 @@ void tst_Collections::forwardDeclared()
{ typedef QSet<T1> C; C *x = 0; /* C::iterator i; */ C::const_iterator j; Q_UNUSED(x) }
}
+#if defined(Q_ALIGNOF) && defined(Q_DECL_ALIGN)
+
+class Q_DECL_ALIGN(4) Aligned4
+{
+ char i;
+public:
+ Aligned4(int i = 0) : i(i) {}
+ bool checkAligned() const
+ {
+ return (quintptr(this) & 3) == 0;
+ }
+
+ inline bool operator==(const Aligned4 &other) const { return i == other.i; }
+ inline bool operator<(const Aligned4 &other) const { return i < other.i; }
+ friend inline int qHash(const Aligned4 &a) { return qHash(a.i); }
+};
+
+class Q_DECL_ALIGN(128) Aligned128
+{
+ char i;
+public:
+ Aligned128(int i = 0) : i(i) {}
+ bool checkAligned() const
+ {
+ return (quintptr(this) & 127) == 0;
+ }
+
+ inline bool operator==(const Aligned128 &other) const { return i == other.i; }
+ inline bool operator<(const Aligned128 &other) const { return i < other.i; }
+ friend inline int qHash(const Aligned128 &a) { return qHash(a.i); }
+};
+
+template<typename C>
+void testVectorAlignment()
+{
+ typedef typename C::value_type Aligned;
+ C container;
+ container.append(Aligned());
+ QVERIFY(container[0].checkAligned());
+
+ for (int i = 0; i < 200; ++i)
+ container.append(Aligned());
+
+ for (int i = 0; i < container.size(); ++i)
+ QVERIFY(container.at(i).checkAligned());
+}
+
+template<typename C>
+void testContiguousCacheAlignment()
+{
+ typedef typename C::value_type Aligned;
+ C container(150);
+ container.append(Aligned());
+ QVERIFY(container[container.firstIndex()].checkAligned());
+
+ for (int i = 0; i < 200; ++i)
+ container.append(Aligned());
+
+ for (int i = container.firstIndex(); i < container.lastIndex(); ++i)
+ QVERIFY(container.at(i).checkAligned());
+}
+
+template<typename C>
+void testAssociativeContainerAlignment()
+{
+ typedef typename C::key_type Key;
+ typedef typename C::mapped_type Value;
+ C container;
+ container.insert(Key(), Value());
+
+ typename C::const_iterator it = container.constBegin();
+ QVERIFY(it.key().checkAligned());
+ QVERIFY(it.value().checkAligned());
+
+ // add some more elements
+ for (int i = 0; i < 200; ++i)
+ container.insert(Key(i), Value(i));
+
+ it = container.constBegin();
+ for ( ; it != container.constEnd(); ++it) {
+ QVERIFY(it.key().checkAligned());
+ QVERIFY(it.value().checkAligned());
+ }
+}
+
+void tst_Collections::alignment()
+{
+ testVectorAlignment<QVector<Aligned4> >();
+ testVectorAlignment<QVector<Aligned128> >();
+ testContiguousCacheAlignment<QContiguousCache<Aligned4> >();
+ testContiguousCacheAlignment<QContiguousCache<Aligned128> >();
+ testAssociativeContainerAlignment<QMap<Aligned4, Aligned4> >();
+ testAssociativeContainerAlignment<QMap<Aligned4, Aligned128> >();
+ testAssociativeContainerAlignment<QMap<Aligned128, Aligned4> >();
+ testAssociativeContainerAlignment<QMap<Aligned128, Aligned128> >();
+ testAssociativeContainerAlignment<QHash<Aligned4, Aligned4> >();
+ testAssociativeContainerAlignment<QHash<Aligned4, Aligned128> >();
+ testAssociativeContainerAlignment<QHash<Aligned128, Aligned4> >();
+ testAssociativeContainerAlignment<QHash<Aligned128, Aligned128> >();
+}
+
+#else
+void tst_Collections::alignment()
+{
+ QSKIP("Compiler doesn't support necessary extension keywords", SkipAll)
+}
+#endif
+
QTEST_APPLESS_MAIN(tst_Collections)
#include "tst_collections.moc"