diff options
author | Samuel Rødal <samuel.rodal@nokia.com> | 2011-08-03 11:03:22 +0200 |
---|---|---|
committer | Samuel Rødal <samuel.rodal@nokia.com> | 2011-08-03 11:03:22 +0200 |
commit | 92c998afb66a2ec900d50cab57929c0a97ad46ac (patch) | |
tree | 1f6219dc64c236c85d7365f8e07ee1df1f27a610 /src/corelib/kernel | |
parent | 6c4dec7bff6f55b0c41729f4a4ab6962a037af15 (diff) | |
parent | 6f4212e5936b96a8be0eacddbfc4dd7ca5abd776 (diff) |
Merge remote branch 'gerrit/master' into refactor
Conflicts:
src/gui/kernel/qapplication_x11.cpp
src/gui/widgets/qlinecontrol.cpp
src/gui/widgets/qlinecontrol_p.h
src/gui/widgets/qtabwidget.h
Change-Id: I90ba893a5553b9ff5658ca0a3221ecf76be4c736
Diffstat (limited to 'src/corelib/kernel')
-rw-r--r-- | src/corelib/kernel/qabstracteventdispatcher.cpp | 210 | ||||
-rw-r--r-- | src/corelib/kernel/qmetaobject.cpp | 25 | ||||
-rw-r--r-- | src/corelib/kernel/qmetaobject_p.h | 3 | ||||
-rw-r--r-- | src/corelib/kernel/qobject.cpp | 32 |
4 files changed, 72 insertions, 198 deletions
diff --git a/src/corelib/kernel/qabstracteventdispatcher.cpp b/src/corelib/kernel/qabstracteventdispatcher.cpp index 1b0707605c..10de2caf62 100644 --- a/src/corelib/kernel/qabstracteventdispatcher.cpp +++ b/src/corelib/kernel/qabstracteventdispatcher.cpp @@ -45,109 +45,10 @@ #include "qthread.h" #include <private/qthread_p.h> #include <private/qcoreapplication_p.h> +#include <private/qfreelist_p.h> QT_BEGIN_NAMESPACE -// we allow for 2^24 = 8^8 = 16777216 simultaneously running timers -static const int TimerIdMask = 0x00ffffff; -static const int TimerSerialMask = ~TimerIdMask & ~0x80000000; -static const int TimerSerialCounter = TimerIdMask + 1; -static const int MaxTimerId = TimerIdMask; - -static int FirstBucket[] = { - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, - 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 -}; - -enum { - FirstBucketOffset = 0, - SecondBucketOffset = sizeof(FirstBucket) / sizeof(FirstBucket[0]), - ThirdBucketOffset = 0x100, - FourthBucketOffset = 0x1000, - FifthBucketOffset = 0x10000, - SixthBucketOffset = 0x100000 -}; - -enum { - FirstBucketSize = SecondBucketOffset, - SecondBucketSize = ThirdBucketOffset - SecondBucketOffset, - ThirdBucketSize = FourthBucketOffset - ThirdBucketOffset, - FourthBucketSize = FifthBucketOffset - FourthBucketOffset, - FifthBucketSize = SixthBucketOffset - FifthBucketOffset, - SixthBucketSize = MaxTimerId - SixthBucketOffset -}; - -static const int BucketSize[] = { - FirstBucketSize, SecondBucketSize, ThirdBucketSize, - FourthBucketSize, FifthBucketSize, SixthBucketSize -}; -enum { NumberOfBuckets = sizeof(BucketSize) / sizeof(BucketSize[0]) }; - -static const int BucketOffset[] = { - FirstBucketOffset, SecondBucketOffset, ThirdBucketOffset, - FourthBucketOffset, FifthBucketOffset, SixthBucketOffset -}; - -static QBasicAtomicPointer<int> timerIds[] = - { Q_BASIC_ATOMIC_INITIALIZER(FirstBucket), - Q_BASIC_ATOMIC_INITIALIZER(0), - Q_BASIC_ATOMIC_INITIALIZER(0), - Q_BASIC_ATOMIC_INITIALIZER(0), - Q_BASIC_ATOMIC_INITIALIZER(0), - Q_BASIC_ATOMIC_INITIALIZER(0) }; - -static void timerIdsDestructorFunction() -{ - // start at one, the first bucket is pre-allocated - for (int i = 1; i < NumberOfBuckets; ++i) - delete [] static_cast<int *>(timerIds[i]); -} -Q_DESTRUCTOR_FUNCTION(timerIdsDestructorFunction) - -static QBasicAtomicInt nextFreeTimerId = Q_BASIC_ATOMIC_INITIALIZER(1); - -// avoid the ABA-problem by using 7 of the top 8 bits of the timerId as a serial number -static inline int prepareNewValueWithSerialNumber(int oldId, int newId) -{ - return (newId & TimerIdMask) | ((oldId + TimerSerialCounter) & TimerSerialMask); -} - -namespace { - template<bool> struct QStaticAssertType; - template<> struct QStaticAssertType<true> { enum { Value = 1 }; }; -} -#define q_static_assert(expr) (void)QStaticAssertType<expr>::Value - -static inline int bucketOffset(int timerId) -{ - q_static_assert(sizeof BucketSize == sizeof BucketOffset); - q_static_assert(sizeof(timerIds) / sizeof(timerIds[0]) == NumberOfBuckets); - - for (int i = 0; i < NumberOfBuckets; ++i) { - if (timerId < BucketSize[i]) - return i; - timerId -= BucketSize[i]; - } - qFatal("QAbstractEventDispatcher: INTERNAL ERROR, timer ID %d is too large", timerId); - return -1; -} - -static inline int bucketIndex(int bucket, int timerId) -{ - return timerId - BucketOffset[bucket]; -} - -static inline int *allocateBucket(int bucket) -{ - // allocate a new bucket - const int size = BucketSize[bucket]; - const int offset = BucketOffset[bucket]; - int *b = new int[size]; - for (int i = 0; i != size; ++i) - b[i] = offset + i + 1; - return b; -} - void QAbstractEventDispatcherPrivate::init() { Q_Q(QAbstractEventDispatcher); @@ -158,79 +59,54 @@ void QAbstractEventDispatcherPrivate::init() } } -// Timer IDs are implemented using a free-list; -// there's a vector initialized with: -// X[i] = i + 1 -// and nextFreeTimerId starts with 1. -// -// Allocating a timer ID involves taking the ID from -// X[nextFreeTimerId] -// updating nextFreeTimerId to this value and returning the old value -// -// When the timer ID is allocated, its cell in the vector is unused (it's a -// free list). As an added protection, we use the cell to store an invalid -// (negative) value that we can later check for integrity. -// -// (continues below). +// we allow for 2^24 = 8^8 = 16777216 simultaneously running timers +struct QtTimerIdFreeListConstants : public QFreeListDefaultConstants +{ + enum + { + InitialNextValue = 1, + BlockCount = 6, + }; + + static const int Sizes[BlockCount]; +}; + +enum { + Offset0 = 0x00000000, + Offset1 = 0x00000040, + Offset2 = 0x00000100, + Offset3 = 0x00001000, + Offset4 = 0x00010000, + Offset5 = 0x00100000, + + Size0 = Offset1 - Offset0, + Size1 = Offset2 - Offset1, + Size2 = Offset3 - Offset2, + Size3 = Offset4 - Offset3, + Size4 = Offset5 - Offset4, + Size5 = QtTimerIdFreeListConstants::MaxIndex - Offset5 +}; + +const int QtTimerIdFreeListConstants::Sizes[QtTimerIdFreeListConstants::BlockCount] = { + Size0, + Size1, + Size2, + Size3, + Size4, + Size5 +}; + +typedef QFreeList<void, QtTimerIdFreeListConstants> QtTimerIdFreeList; +Q_GLOBAL_STATIC(QtTimerIdFreeList, timerIdFreeList) + int QAbstractEventDispatcherPrivate::allocateTimerId() { - int timerId, newTimerId; - int at, *b; - do { - timerId = nextFreeTimerId; //.loadAcquire(); // ### FIXME Proper memory ordering semantics - - // which bucket are we looking in? - int which = timerId & TimerIdMask; - int bucket = bucketOffset(which); - at = bucketIndex(bucket, which); - b = timerIds[bucket]; - - if (!b) { - // allocate a new bucket - b = allocateBucket(bucket); - if (!timerIds[bucket].testAndSetRelease(0, b)) { - // another thread won the race to allocate the bucket - delete [] b; - b = timerIds[bucket]; - } - } - - newTimerId = prepareNewValueWithSerialNumber(timerId, b[at]); - } while (!nextFreeTimerId.testAndSetRelaxed(timerId, newTimerId)); - - b[at] = -timerId; - - return timerId; + return timerIdFreeList()->next(); } -// Releasing a timer ID requires putting the current ID back in the vector; -// we do it by setting: -// X[timerId] = nextFreeTimerId; -// then we update nextFreeTimerId to the timer we've just released -// -// The extra code in allocateTimerId and releaseTimerId are ABA prevention -// and bucket memory. The buckets are simply to make sure we allocate only -// the necessary number of timers. See above. -// -// ABA prevention simply adds a value to 7 of the top 8 bits when resetting -// nextFreeTimerId. void QAbstractEventDispatcherPrivate::releaseTimerId(int timerId) { - int which = timerId & TimerIdMask; - int bucket = bucketOffset(which); - int at = bucketIndex(bucket, which); - int *b = timerIds[bucket]; - - Q_ASSERT_X(timerId == -b[at], "QAbstractEventDispatcher::releaseTimerId", - "Internal error: timer ID not found"); - - int freeId, newTimerId; - do { - freeId = nextFreeTimerId;//.loadAcquire(); // ### FIXME Proper memory ordering semantics - b[at] = freeId & TimerIdMask; - - newTimerId = prepareNewValueWithSerialNumber(freeId, timerId); - } while (!nextFreeTimerId.testAndSetRelease(freeId, newTimerId)); + timerIdFreeList()->release(timerId); } /*! diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp index c8ac15c1fa..b6de002cf4 100644 --- a/src/corelib/kernel/qmetaobject.cpp +++ b/src/corelib/kernel/qmetaobject.cpp @@ -859,20 +859,31 @@ QMetaProperty QMetaObject::property(int index) const if (flags & EnumOrFlag) { result.menum = enumerator(indexOfEnumerator(type)); if (!result.menum.isValid()) { - QByteArray enum_name = type; - QByteArray scope_name = d.stringdata; - int s = enum_name.lastIndexOf("::"); - if (s > 0) { - scope_name = enum_name.left(s); - enum_name = enum_name.mid(s + 2); + const char *enum_name = type; + const char *scope_name = d.stringdata; + char *scope_buffer = 0; + + const char *colon = strrchr(enum_name, ':'); + // ':' will always appear in pairs + Q_ASSERT(colon <= enum_name || *(colon-1) == ':'); + if (colon > enum_name) { + int len = colon-enum_name-1; + scope_buffer = (char *)qMalloc(len+1); + qMemCopy(scope_buffer, enum_name, len); + scope_buffer[len] = '\0'; + scope_name = scope_buffer; + enum_name = colon+1; } + const QMetaObject *scope = 0; - if (scope_name == "Qt") + if (qstrcmp(scope_name, "Qt") == 0) scope = &QObject::staticQtMetaObject; else scope = QMetaObject_findMetaObject(this, scope_name); if (scope) result.menum = scope->enumerator(scope->indexOfEnumerator(enum_name)); + if (scope_buffer) + qFree(scope_buffer); } } } diff --git a/src/corelib/kernel/qmetaobject_p.h b/src/corelib/kernel/qmetaobject_p.h index 63605ecadb..5da936aab0 100644 --- a/src/corelib/kernel/qmetaobject_p.h +++ b/src/corelib/kernel/qmetaobject_p.h @@ -101,7 +101,8 @@ enum MethodFlags { }; enum MetaObjectFlags { - DynamicMetaObject = 0x01 + DynamicMetaObject = 0x01, + RequiresVariantMetaObject = 0x02 }; class QMutex; diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index a282ae007c..7652ec4871 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -60,7 +60,6 @@ #include <qsharedpointer.h> #include <private/qorderedmutexlocker_p.h> -#include <private/qmutexpool_p.h> #include <new> @@ -95,35 +94,22 @@ static int *queuedConnectionTypes(const QList<QByteArray> &typeNames) return types; } -static QBasicAtomicPointer<QMutexPool> signalSlotMutexes = Q_BASIC_ATOMIC_INITIALIZER(0); -static QBasicAtomicInt objectCount = Q_BASIC_ATOMIC_INITIALIZER(0); +static QBasicMutex _q_ObjectMutexPool[131]; /** \internal * mutex to be locked when accessing the connectionlists or the senders list */ static inline QMutex *signalSlotLock(const QObject *o) { - if (!signalSlotMutexes) { - QMutexPool *mp = new QMutexPool; - if (!signalSlotMutexes.testAndSetOrdered(0, mp)) { - delete mp; - } - } - return signalSlotMutexes->get(o); + return static_cast<QMutex *>(&_q_ObjectMutexPool[ + uint(quintptr(o)) % sizeof(_q_ObjectMutexPool)/sizeof(QBasicMutex)]); } extern "C" Q_CORE_EXPORT void qt_addObject(QObject *) -{ - objectCount.ref(); -} +{} extern "C" Q_CORE_EXPORT void qt_removeObject(QObject *) -{ - if(!objectCount.deref()) { - QMutexPool *old = signalSlotMutexes.fetchAndStoreAcquire(0); - delete old; - } -} +{} struct QConnectionSenderSwitcher { QObject *receiver; @@ -879,7 +865,7 @@ QObject::~QObject() if (c->next) c->next->prev = c->prev; } if (needToUnlock) - m->unlockInline(); + m->unlock(); connectionList.first = c->nextConnectionList; delete c; @@ -903,7 +889,7 @@ QObject::~QObject() bool needToUnlock = QOrderedMutexLocker::relock(signalSlotMutex, m); //the node has maybe been removed while the mutex was unlocked in relock? if (!node || node->sender != sender) { - m->unlockInline(); + m->unlock(); continue; } node->receiver = 0; @@ -913,7 +899,7 @@ QObject::~QObject() node = node->next; if (needToUnlock) - m->unlockInline(); + m->unlock(); } } @@ -3077,7 +3063,7 @@ bool QMetaObjectPrivate::disconnectHelper(QObjectPrivate::Connection *c, } if (needToUnlock) - receiverMutex->unlockInline(); + receiverMutex->unlock(); c->receiver = 0; |