summaryrefslogtreecommitdiffstats
path: root/src/corelib/tools/qmap.h
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 /src/corelib/tools/qmap.h
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 'src/corelib/tools/qmap.h')
-rw-r--r--src/corelib/tools/qmap.h20
1 files changed, 15 insertions, 5 deletions
diff --git a/src/corelib/tools/qmap.h b/src/corelib/tools/qmap.h
index 688aca6..20980e7 100644
--- a/src/corelib/tools/qmap.h
+++ b/src/corelib/tools/qmap.h
@@ -74,10 +74,13 @@ struct Q_CORE_EXPORT QMapData
uint randomBits;
uint insertInOrder : 1;
uint sharable : 1;
+ uint strictAlignment : 1;
- static QMapData *createData();
+ static QMapData *createData(); // ### Qt5 remove me
+ static QMapData *createData(int alignment);
void continueFreeData(int offset);
- Node *node_create(Node *update[], int offset);
+ Node *node_create(Node *update[], int offset); // ### Qt5 remove me
+ Node *node_create(Node *update[], int offset, int alignment);
void node_delete(Node *update[], int offset, Node *node);
#ifdef QT_QMAP_DEBUG
uint adjust_ptr(Node *node);
@@ -145,6 +148,13 @@ class QMap
};
static inline int payload() { return sizeof(PayloadNode) - sizeof(QMapData::Node *); }
+ static inline int alignment() {
+#ifdef Q_ALIGNOF
+ return qMax(sizeof(void*), Q_ALIGNOF(Node));
+#else
+ return 0;
+#endif
+ }
static inline Node *concrete(QMapData::Node *node) {
return reinterpret_cast<Node *>(reinterpret_cast<char *>(node) - payload());
}
@@ -414,7 +424,7 @@ template <class Key, class T>
Q_INLINE_TEMPLATE typename QMapData::Node *
QMap<Key, T>::node_create(QMapData *adt, QMapData::Node *aupdate[], const Key &akey, const T &avalue)
{
- QMapData::Node *abstractNode = adt->node_create(aupdate, payload());
+ QMapData::Node *abstractNode = adt->node_create(aupdate, payload(), alignment());
QT_TRY {
Node *concreteNode = concrete(abstractNode);
new (&concreteNode->key) Key(akey);
@@ -715,7 +725,7 @@ template <class Key, class T>
Q_OUTOFLINE_TEMPLATE void QMap<Key, T>::detach_helper()
{
union { QMapData *d; QMapData::Node *e; } x;
- x.d = QMapData::createData();
+ x.d = QMapData::createData(alignment());
if (d->size) {
x.d->insertInOrder = true;
QMapData::Node *update[QMapData::LastLevel + 1];
@@ -905,7 +915,7 @@ Q_OUTOFLINE_TEMPLATE bool QMap<Key, T>::operator==(const QMap<Key, T> &other) co
template <class Key, class T>
Q_OUTOFLINE_TEMPLATE QMap<Key, T>::QMap(const std::map<Key, T> &other)
{
- d = QMapData::createData();
+ d = QMapData::createData(alignment());
d->insertInOrder = true;
typename std::map<Key,T>::const_iterator it = other.end();
while (it != other.begin()) {