summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/3rdparty/harfbuzz/src/harfbuzz-external.h2
-rw-r--r--src/3rdparty/harfbuzz/tests/linebreaking/harfbuzz-qt.cpp2
-rw-r--r--src/corelib/arch/qatomic_bootstrap.h23
-rw-r--r--src/corelib/global/qglobal.cpp7
-rw-r--r--src/corelib/global/qglobal.h6
-rw-r--r--src/corelib/io/qfilesystemwatcher_inotify.cpp2
-rw-r--r--src/corelib/kernel/qabstracteventdispatcher.cpp210
-rw-r--r--src/corelib/kernel/qmetaobject.cpp25
-rw-r--r--src/corelib/kernel/qmetaobject_p.h3
-rw-r--r--src/corelib/kernel/qobject.cpp32
-rw-r--r--src/corelib/plugin/qlibrary.cpp10
-rw-r--r--src/corelib/plugin/qlibrary.h8
-rw-r--r--src/corelib/plugin/qlibrary_p.h4
-rw-r--r--src/corelib/plugin/qlibrary_unix.cpp14
-rw-r--r--src/corelib/plugin/qlibrary_win.cpp8
-rw-r--r--src/corelib/plugin/qsystemlibrary_p.h8
-rw-r--r--src/corelib/thread/qmutex.cpp435
-rw-r--r--src/corelib/thread/qmutex.h121
-rw-r--r--src/corelib/thread/qmutex_linux.cpp138
-rw-r--r--src/corelib/thread/qmutex_mac.cpp96
-rw-r--r--src/corelib/thread/qmutex_p.h70
-rw-r--r--src/corelib/thread/qmutex_unix.cpp116
-rw-r--r--src/corelib/thread/qmutex_win.cpp10
-rw-r--r--src/corelib/thread/qorderedmutexlocker_p.h12
-rw-r--r--src/corelib/thread/qwaitcondition_unix.cpp2
-rw-r--r--src/corelib/thread/qwaitcondition_win.cpp2
-rw-r--r--src/corelib/thread/thread.pri9
-rw-r--r--src/corelib/tools/qbytearray.cpp21
-rw-r--r--src/corelib/tools/qbytearray.h18
-rw-r--r--src/corelib/tools/qchar.cpp13
-rw-r--r--src/corelib/tools/qfreelist.cpp67
-rw-r--r--src/corelib/tools/qfreelist_p.h294
-rw-r--r--src/corelib/tools/qharfbuzz.cpp2
-rw-r--r--src/corelib/tools/qshareddata.h3
-rw-r--r--src/corelib/tools/qstring.cpp18
-rw-r--r--src/corelib/tools/qstring.h35
-rw-r--r--src/corelib/tools/qstringbuilder.cpp5
-rw-r--r--src/corelib/tools/qstringbuilder.h29
-rw-r--r--src/corelib/tools/tools.pri2
-rw-r--r--src/dbus/qdbus_symbols.cpp9
-rw-r--r--src/dbus/qdbus_symbols_p.h4
-rw-r--r--src/dbus/qdbusmetaobject.cpp12
-rw-r--r--src/gui/image/qbmphandler.cpp64
-rw-r--r--src/gui/image/qtiffhandler.cpp13
-rw-r--r--src/gui/math3d/qmatrix4x4.cpp16
-rw-r--r--src/gui/painting/qpaintengine_raster.cpp7
-rw-r--r--src/gui/painting/qpaintengineex.cpp10
-rw-r--r--src/gui/painting/qpaintengineex_p.h1
-rw-r--r--src/gui/text/qfontengine_p.h3
-rw-r--r--src/gui/text/qrawfont.cpp8
-rw-r--r--src/gui/text/qrawfont.h8
-rw-r--r--src/gui/text/qrawfont_ft.cpp4
-rw-r--r--src/gui/text/qrawfont_p.h2
-rw-r--r--src/gui/text/qrawfont_qpa.cpp2
-rw-r--r--src/gui/text/qtextcontrol.cpp3
-rw-r--r--src/gui/text/qtextengine.cpp2
-rw-r--r--src/gui/util/qvalidator.cpp101
-rw-r--r--src/gui/util/qvalidator.h27
-rw-r--r--src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp10
-rw-r--r--src/opengl/qgl_x11.cpp8
-rw-r--r--src/opengl/qglpixelbuffer_x11.cpp2
-rw-r--r--src/plugins/platforms/xlib/qxlibstatic.cpp6
-rw-r--r--src/sql/models/qsqlrelationaltablemodel.cpp36
-rw-r--r--src/testlib/testlib.pro2
-rw-r--r--src/widgets/platforms/mac/qrawfont_mac.cpp2
-rw-r--r--src/widgets/platforms/win/qrawfont_win.cpp8
-rw-r--r--src/widgets/platforms/x11/qkeymapper_x11.cpp2
-rw-r--r--src/widgets/widgets/qtabwidget.h3
-rw-r--r--src/winmain/winmain.pro2
69 files changed, 1462 insertions, 797 deletions
diff --git a/src/3rdparty/harfbuzz/src/harfbuzz-external.h b/src/3rdparty/harfbuzz/src/harfbuzz-external.h
index 5fff35fe50..1f7ae1c902 100644
--- a/src/3rdparty/harfbuzz/src/harfbuzz-external.h
+++ b/src/3rdparty/harfbuzz/src/harfbuzz-external.h
@@ -144,7 +144,7 @@ HB_CharCategory HB_GetUnicodeCharCategory(HB_UChar32 ch);
int HB_GetUnicodeCharCombiningClass(HB_UChar32 ch);
HB_UChar16 HB_GetMirroredChar(HB_UChar16 ch);
-void *HB_Library_Resolve(const char *library, int version, const char *symbol);
+void (*HB_Library_Resolve(const char *library, int version, const char *symbol))();
HB_END_HEADER
diff --git a/src/3rdparty/harfbuzz/tests/linebreaking/harfbuzz-qt.cpp b/src/3rdparty/harfbuzz/tests/linebreaking/harfbuzz-qt.cpp
index f0048b75ef..2c261639ad 100644
--- a/src/3rdparty/harfbuzz/tests/linebreaking/harfbuzz-qt.cpp
+++ b/src/3rdparty/harfbuzz/tests/linebreaking/harfbuzz-qt.cpp
@@ -79,7 +79,7 @@ void HB_GetGraphemeAndLineBreakClass(HB_UChar32 ch, HB_GraphemeClass *grapheme,
*lineBreak = (HB_LineBreakClass) prop->line_break_class;
}
-void *HB_Library_Resolve(const char *library, int version, const char *symbol)
+void (*HB_Library_Resolve(const char *library, int version, const char *symbol))()
{
return QLibrary::resolve(library, version, symbol);
}
diff --git a/src/corelib/arch/qatomic_bootstrap.h b/src/corelib/arch/qatomic_bootstrap.h
index ecce758e71..74dc6cfbb2 100644
--- a/src/corelib/arch/qatomic_bootstrap.h
+++ b/src/corelib/arch/qatomic_bootstrap.h
@@ -75,13 +75,34 @@ inline bool QBasicAtomicInt::testAndSetRelease(int expectedValue, int newValue)
return testAndSetOrdered(expectedValue, newValue);
}
-inline int QBasicAtomicInt::fetchAndAddRelaxed(int valueToAdd)
+inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue)
+{
+ return testAndSetOrdered(expectedValue, newValue);
+}
+
+inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd)
{
int returnValue = _q_value;
_q_value += valueToAdd;
return returnValue;
}
+inline int QBasicAtomicInt::fetchAndAddAcquire(int valueToAdd)
+{
+ return fetchAndAddOrdered(valueToAdd);
+}
+
+inline int QBasicAtomicInt::fetchAndAddRelease(int valueToAdd)
+{
+ return fetchAndAddOrdered(valueToAdd);
+}
+
+inline int QBasicAtomicInt::fetchAndAddRelaxed(int valueToAdd)
+{
+ return fetchAndAddOrdered(valueToAdd);
+}
+
+
template <typename T>
Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue)
{
diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp
index a59cbf9382..452679c7d7 100644
--- a/src/corelib/global/qglobal.cpp
+++ b/src/corelib/global/qglobal.cpp
@@ -718,6 +718,13 @@ QT_BEGIN_NAMESPACE
\sa QtMsgHandler, qInstallMsgHandler()
*/
+/*! \typedef QFunctionPointer
+ \relates <QtGlobal>
+
+ This is a typedef for \c{void (*)()}, a pointer to a function that takes
+ no arguments and returns void.
+*/
+
/*! \macro qint64 Q_INT64_C(literal)
\relates <QtGlobal>
diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h
index e4084ed91f..2f6f33efca 100644
--- a/src/corelib/global/qglobal.h
+++ b/src/corelib/global/qglobal.h
@@ -281,7 +281,7 @@ namespace QT_NAMESPACE {}
# define Q_OS_VXWORKS
#elif defined(__MAKEDEPEND__)
#else
-# error "Qt has not been ported to this OS - talk to qt-bugs@trolltech.com"
+# error "Qt has not been ported to this OS - talk to qt-info@nokia.com"
#endif
#if defined(Q_OS_WIN32) || defined(Q_OS_WIN64) || defined(Q_OS_WINCE)
@@ -794,7 +794,7 @@ namespace QT_NAMESPACE {}
# define Q_CC_NOKIAX86
#else
-# error "Qt has not been tested with this compiler - talk to qt-bugs@trolltech.com"
+# error "Qt has not been tested with this compiler - talk to qt-info@nokia.com"
#endif
@@ -1807,6 +1807,8 @@ Q_CORE_EXPORT void qt_message_output(QtMsgType, const char *buf);
typedef void (*QtMsgHandler)(QtMsgType, const char *);
Q_CORE_EXPORT QtMsgHandler qInstallMsgHandler(QtMsgHandler);
+typedef void (*QFunctionPointer)();
+
#if !defined(Q_UNIMPLEMENTED)
# define Q_UNIMPLEMENTED() qWarning("%s:%d: %s: Unimplemented code.", __FILE__, __LINE__, Q_FUNC_INFO)
#endif
diff --git a/src/corelib/io/qfilesystemwatcher_inotify.cpp b/src/corelib/io/qfilesystemwatcher_inotify.cpp
index 5c5223eb1c..ef302243da 100644
--- a/src/corelib/io/qfilesystemwatcher_inotify.cpp
+++ b/src/corelib/io/qfilesystemwatcher_inotify.cpp
@@ -131,7 +131,7 @@
# define __NR_inotify_rm_watch 286
# define __NR_inotify_init1 328
#else
-# error "This architecture is not supported. Please talk to qt-bugs@trolltech.com"
+# error "This architecture is not supported. Please talk to qt-info@nokia.com"
#endif
#if !defined(IN_CLOEXEC) && defined(O_CLOEXEC) && defined(__NR_inotify_init1)
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;
diff --git a/src/corelib/plugin/qlibrary.cpp b/src/corelib/plugin/qlibrary.cpp
index 314ccd7861..45515f32e1 100644
--- a/src/corelib/plugin/qlibrary.cpp
+++ b/src/corelib/plugin/qlibrary.cpp
@@ -447,7 +447,7 @@ QLibraryPrivate::~QLibraryPrivate()
}
}
-void *QLibraryPrivate::resolve(const char *symbol)
+QFunctionPointer QLibraryPrivate::resolve(const char *symbol)
{
if (!pHnd)
return 0;
@@ -1129,7 +1129,7 @@ void QLibrary::setFileNameAndVersion(const QString &fileName, const QString &ver
Note: In Symbian resolving with symbol names works only if the loaded
library was built as STDDLL. Otherwise, the ordinals must be used.
*/
-void *QLibrary::resolve(const char *symbol)
+QFunctionPointer QLibrary::resolve(const char *symbol)
{
if (!isLoaded() && !load())
return 0;
@@ -1152,7 +1152,7 @@ void *QLibrary::resolve(const char *symbol)
\sa resolve()
*/
-void *QLibrary::resolve(const QString &fileName, const char *symbol)
+QFunctionPointer QLibrary::resolve(const QString &fileName, const char *symbol)
{
QLibrary library(fileName);
return library.resolve(symbol);
@@ -1175,7 +1175,7 @@ void *QLibrary::resolve(const QString &fileName, const char *symbol)
\sa resolve()
*/
-void *QLibrary::resolve(const QString &fileName, int verNum, const char *symbol)
+QFunctionPointer QLibrary::resolve(const QString &fileName, int verNum, const char *symbol)
{
QLibrary library(fileName, verNum);
return library.resolve(symbol);
@@ -1199,7 +1199,7 @@ void *QLibrary::resolve(const QString &fileName, int verNum, const char *symbol)
\sa resolve()
*/
-void *QLibrary::resolve(const QString &fileName, const QString &version, const char *symbol)
+QFunctionPointer QLibrary::resolve(const QString &fileName, const QString &version, const char *symbol)
{
QLibrary library(fileName, version);
return library.resolve(symbol);
diff --git a/src/corelib/plugin/qlibrary.h b/src/corelib/plugin/qlibrary.h
index 0154e949b3..e3f557dd7d 100644
--- a/src/corelib/plugin/qlibrary.h
+++ b/src/corelib/plugin/qlibrary.h
@@ -79,10 +79,10 @@ public:
explicit QLibrary(const QString& fileName, const QString &version, QObject *parent = 0);
~QLibrary();
- void *resolve(const char *symbol);
- static void *resolve(const QString &fileName, const char *symbol);
- static void *resolve(const QString &fileName, int verNum, const char *symbol);
- static void *resolve(const QString &fileName, const QString &version, const char *symbol);
+ QFunctionPointer resolve(const char *symbol);
+ static QFunctionPointer resolve(const QString &fileName, const char *symbol);
+ static QFunctionPointer resolve(const QString &fileName, int verNum, const char *symbol);
+ static QFunctionPointer resolve(const QString &fileName, const QString &version, const char *symbol);
bool load();
bool unload();
diff --git a/src/corelib/plugin/qlibrary_p.h b/src/corelib/plugin/qlibrary_p.h
index 4f66bc26a0..c6804955d9 100644
--- a/src/corelib/plugin/qlibrary_p.h
+++ b/src/corelib/plugin/qlibrary_p.h
@@ -87,7 +87,7 @@ public:
bool loadPlugin(); // loads and resolves instance
bool unload();
void release();
- void *resolve(const char *);
+ QFunctionPointer resolve(const char *);
static QLibraryPrivate *findOrCreate(const QString &fileName, const QString &version = QString());
@@ -108,7 +108,7 @@ private:
bool load_sys();
bool unload_sys();
- void *resolve_sys(const char *);
+ QFunctionPointer resolve_sys(const char *);
QAtomicInt libraryRefCount;
QAtomicInt libraryUnloadCount;
diff --git a/src/corelib/plugin/qlibrary_unix.cpp b/src/corelib/plugin/qlibrary_unix.cpp
index 0a7e841519..d3b08e1acf 100644
--- a/src/corelib/plugin/qlibrary_unix.cpp
+++ b/src/corelib/plugin/qlibrary_unix.cpp
@@ -267,29 +267,29 @@ bool QLibraryPrivate::unload_sys()
}
#ifdef Q_OS_MAC
-Q_CORE_EXPORT void *qt_mac_resolve_sys(void *handle, const char *symbol)
+Q_CORE_EXPORT QFunctionPointer qt_mac_resolve_sys(void *handle, const char *symbol)
{
- return dlsym(handle, symbol);
+ return QFunctionPointer(dlsym(handle, symbol));
}
#endif
-void* QLibraryPrivate::resolve_sys(const char* symbol)
+QFunctionPointer QLibraryPrivate::resolve_sys(const char* symbol)
{
#if defined(QT_AOUT_UNDERSCORE)
// older a.out systems add an underscore in front of symbols
char* undrscr_symbol = new char[strlen(symbol)+2];
undrscr_symbol[0] = '_';
strcpy(undrscr_symbol+1, symbol);
- void* address = dlsym(pHnd, undrscr_symbol);
+ QFunctionPointer address = QFunctionPointer(dlsym(pHnd, undrscr_symbol));
delete [] undrscr_symbol;
#elif defined(QT_HPUX_LD)
- void* address = 0;
+ QFunctionPointer address = 0;
if (shl_findsym((shl_t*)&pHnd, symbol, TYPE_UNDEFINED, &address) < 0)
address = 0;
#elif defined (QT_NO_DYNAMIC_LIBRARY)
- void *address = 0;
+ QFunctionPointer address = 0;
#else
- void* address = dlsym(pHnd, symbol);
+ QFunctionPointer address = QFunctionPointer(dlsym(pHnd, symbol));
#endif
if (!address) {
errorString = QLibrary::tr("Cannot resolve symbol \"%1\" in %2: %3").arg(
diff --git a/src/corelib/plugin/qlibrary_win.cpp b/src/corelib/plugin/qlibrary_win.cpp
index 667d9cca45..4eeb2fc441 100644
--- a/src/corelib/plugin/qlibrary_win.cpp
+++ b/src/corelib/plugin/qlibrary_win.cpp
@@ -113,12 +113,12 @@ bool QLibraryPrivate::unload_sys()
return true;
}
-void* QLibraryPrivate::resolve_sys(const char* symbol)
+QFunctionPointer QLibraryPrivate::resolve_sys(const char* symbol)
{
#ifdef Q_OS_WINCE
- void* address = (void*)GetProcAddress(pHnd, (const wchar_t*)QString::fromLatin1(symbol).utf16());
+ FARPROC address = GetProcAddress(pHnd, (const wchar_t*)QString::fromLatin1(symbol).utf16());
#else
- void* address = (void*)GetProcAddress(pHnd, symbol);
+ FARPROC address = GetProcAddress(pHnd, symbol);
#endif
if (!address) {
errorString = QLibrary::tr("Cannot resolve symbol \"%1\" in %2: %3").arg(
@@ -126,6 +126,6 @@ void* QLibraryPrivate::resolve_sys(const char* symbol)
} else {
errorString.clear();
}
- return address;
+ return QFunctionPointer(address);
}
QT_END_NAMESPACE
diff --git a/src/corelib/plugin/qsystemlibrary_p.h b/src/corelib/plugin/qsystemlibrary_p.h
index f20d0b6b9d..3298f05b8f 100644
--- a/src/corelib/plugin/qsystemlibrary_p.h
+++ b/src/corelib/plugin/qsystemlibrary_p.h
@@ -78,20 +78,20 @@ public:
return (m_handle != 0);
}
- void *resolve(const char *symbol)
+ QFunctionPointer resolve(const char *symbol)
{
if (!m_didLoad)
load();
if (!m_handle)
return 0;
#ifdef Q_OS_WINCE
- return (void*)GetProcAddress(m_handle, (const wchar_t*)QString::fromLatin1(symbol).utf16());
+ return QFunctionPointer(GetProcAddress(m_handle, (const wchar_t*)QString::fromLatin1(symbol).utf16()));
#else
- return (void*)GetProcAddress(m_handle, symbol);
+ return QFunctionPointer(GetProcAddress(m_handle, symbol));
#endif
}
- static void *resolve(const QString &libraryName, const char *symbol)
+ static QFunctionPointer resolve(const QString &libraryName, const char *symbol)
{
return QSystemLibrary(libraryName).resolve(symbol);
}
diff --git a/src/corelib/thread/qmutex.cpp b/src/corelib/thread/qmutex.cpp
index 3e3bf8ff13..c90b44be6c 100644
--- a/src/corelib/thread/qmutex.cpp
+++ b/src/corelib/thread/qmutex.cpp
@@ -49,9 +49,26 @@
#include "qthread.h"
#include "qmutex_p.h"
+#ifndef Q_OS_LINUX
+#include "private/qfreelist_p.h"
+#endif
+
QT_BEGIN_NAMESPACE
/*!
+ \class QBasicMutex
+ \brief QMutex POD
+ \internal
+
+ \ingroup thread
+
+ - Can be used as global static object.
+ - Always non-recursive
+ - Do not use tryLock with timeout > 0, else you can have a leak (see the ~QMutex destructor)
+*/
+
+
+/*!
\class QMutex
\brief The QMutex class provides access serialization between threads.
@@ -122,8 +139,12 @@ QT_BEGIN_NAMESPACE
\sa lock(), unlock()
*/
QMutex::QMutex(RecursionMode mode)
- : d(new QMutexPrivate(mode))
-{ }
+{
+ if (mode == Recursive)
+ d = new QRecursiveMutexPrivate;
+ else
+ d = 0;
+}
/*!
Destroys the mutex.
@@ -131,9 +152,18 @@ QMutex::QMutex(RecursionMode mode)
\warning Destroying a locked mutex may result in undefined behavior.
*/
QMutex::~QMutex()
-{ delete static_cast<QMutexPrivate *>(d); }
+{
+ if (isRecursive())
+ delete static_cast<QRecursiveMutexPrivate *>(d._q_value);
+ else if (d) {
+#ifndef Q_OS_LINUX
+ if (d->possiblyUnlocked && tryLock()) { unlock(); return; }
+#endif
+ qWarning("QMutex: destroying locked mutex");
+ }
+}
-/*!
+/*! \fn void QMutex::lock()
Locks the mutex. If another thread has locked the mutex then this
call will block until that thread has unlocked it.
@@ -145,40 +175,8 @@ QMutex::~QMutex()
\sa unlock()
*/
-void QMutex::lock()
-{
- QMutexPrivate *d = static_cast<QMutexPrivate *>(this->d);
- Qt::HANDLE self;
-
- if (d->recursive) {
- self = QThread::currentThreadId();
- if (d->owner == self) {
- ++d->count;
- Q_ASSERT_X(d->count != 0, "QMutex::lock", "Overflow in recursion counter");
- return;
- }
- bool isLocked = d->contenders.testAndSetAcquire(0, 1);
- if (!isLocked) {
- // didn't get the lock, wait for it
- isLocked = d->wait();
- Q_ASSERT_X(isLocked, "QMutex::lock",
- "Internal error, infinite wait has timed out.");
- }
-
- d->owner = self;
- ++d->count;
- Q_ASSERT_X(d->count != 0, "QMutex::lock", "Overflow in recursion counter");
- return;
- }
-
- bool isLocked = d->contenders.testAndSetAcquire(0, 1);
- if (!isLocked) {
- lockInternal();
- }
-}
-
-/*!
+/*!\fn bool QMutex::trylock()
Attempts to lock the mutex. If the lock was obtained, this function
returns true. If another thread has locked the mutex, this
function returns false immediately.
@@ -195,36 +193,9 @@ void QMutex::lock()
\sa lock(), unlock()
*/
-bool QMutex::tryLock()
-{
- QMutexPrivate *d = static_cast<QMutexPrivate *>(this->d);
- Qt::HANDLE self;
- if (d->recursive) {
- self = QThread::currentThreadId();
- if (d->owner == self) {
- ++d->count;
- Q_ASSERT_X(d->count != 0, "QMutex::tryLock", "Overflow in recursion counter");
- return true;
- }
-
- bool isLocked = d->contenders.testAndSetAcquire(0, 1);
- if (!isLocked) {
- // some other thread has the mutex locked, or we tried to
- // recursively lock an non-recursive mutex
- return isLocked;
- }
-
- d->owner = self;
- ++d->count;
- Q_ASSERT_X(d->count != 0, "QMutex::tryLock", "Overflow in recursion counter");
- return isLocked;
- }
-
- return d->contenders.testAndSetAcquire(0, 1);
-}
-
-/*! \overload
+/*! \fn bool QMutex::tryLock(int timeout)
+ \overload
Attempts to lock the mutex. This function returns true if the lock
was obtained; otherwise it returns false. If another thread has
@@ -247,81 +218,30 @@ bool QMutex::tryLock()
\sa lock(), unlock()
*/
-bool QMutex::tryLock(int timeout)
-{
- QMutexPrivate *d = static_cast<QMutexPrivate *>(this->d);
- Qt::HANDLE self;
- if (d->recursive) {
- self = QThread::currentThreadId();
- if (d->owner == self) {
- ++d->count;
- Q_ASSERT_X(d->count != 0, "QMutex::tryLock", "Overflow in recursion counter");
- return true;
- }
- bool isLocked = d->contenders.testAndSetAcquire(0, 1);
- if (!isLocked) {
- // didn't get the lock, wait for it
- isLocked = d->wait(timeout);
- if (!isLocked)
- return false;
- }
-
- d->owner = self;
- ++d->count;
- Q_ASSERT_X(d->count != 0, "QMutex::tryLock", "Overflow in recursion counter");
- return true;
- }
-
- return (d->contenders.testAndSetAcquire(0, 1)
- // didn't get the lock, wait for it
- || d->wait(timeout));
-}
-
-
-/*!
+/*! \fn void QMutex::unlock()
Unlocks the mutex. Attempting to unlock a mutex in a different
thread to the one that locked it results in an error. Unlocking a
mutex that is not locked results in undefined behavior.
\sa lock()
*/
-void QMutex::unlock()
-{
- QMutexPrivate *d = static_cast<QMutexPrivate *>(this->d);
- if (d->recursive) {
- if (!--d->count) {
- d->owner = 0;
- if (!d->contenders.testAndSetRelease(1, 0))
- d->wakeUp();
- }
- } else {
- if (!d->contenders.testAndSetRelease(1, 0))
- d->wakeUp();
- }
-}
/*!
- \fn bool QMutex::locked()
-
- Returns true if the mutex is locked by another thread; otherwise
- returns false.
-
- It is generally a bad idea to use this function, because code
- that uses it has a race condition. Use tryLock() and unlock()
- instead.
-
- \oldcode
- bool isLocked = mutex.locked();
- \newcode
- bool isLocked = true;
- if (mutex.tryLock()) {
- mutex.unlock();
- isLocked = false;
- }
- \endcode
+ \fn void QMutex::isRecursive()
+ \since 5.0
+
+ Returns true if the mutex is recursive
+
*/
+bool QBasicMutex::isRecursive() {
+ QMutexPrivate *d = this->d;
+ if (quintptr(d) <= 0x3)
+ return false;
+ return d->recursive;
+}
+
/*!
\class QMutexLocker
@@ -418,96 +338,217 @@ void QMutex::unlock()
\sa unlock()
*/
+#ifndef Q_OS_LINUX //linux implementation is in qmutex_linux.cpp
/*!
- \fn QMutex::QMutex(bool recursive)
-
- Use the constructor that takes a RecursionMode parameter instead.
-*/
-
-/*!
- \internal helper for lockInline()
+ \internal helper for lock()
*/
-void QMutex::lockInternal()
+bool QBasicMutex::lockInternal(int timeout)
{
- QMutexPrivate *d = static_cast<QMutexPrivate *>(this->d);
-
- if (QThread::idealThreadCount() == 1) {
- // don't spin on single cpu machines
- bool isLocked = d->wait();
- Q_ASSERT_X(isLocked, "QMutex::lock",
- "Internal error, infinite wait has timed out.");
- Q_UNUSED(isLocked);
- return;
- }
+ while (!fastTryLock()) {
+ QMutexPrivate *d = this->d;
+ if (!d) // if d is 0, the mutex is unlocked
+ continue;
- QElapsedTimer elapsedTimer;
- elapsedTimer.start();
- do {
- qint64 spinTime = elapsedTimer.nsecsElapsed();
- if (spinTime > d->maximumSpinTime) {
- // didn't get the lock, wait for it, since we're not going to gain anything by spinning more
- elapsedTimer.start();
- bool isLocked = d->wait();
- Q_ASSERT_X(isLocked, "QMutex::lock",
- "Internal error, infinite wait has timed out.");
- Q_UNUSED(isLocked);
-
- qint64 maximumSpinTime = d->maximumSpinTime;
- qint64 averageWaitTime = d->averageWaitTime;
- qint64 actualWaitTime = elapsedTimer.nsecsElapsed();
- if (actualWaitTime < (QMutexPrivate::MaximumSpinTimeThreshold * 3 / 2)) {
- // measure the wait times
- averageWaitTime = d->averageWaitTime = qMin((averageWaitTime + actualWaitTime) / 2, qint64(QMutexPrivate::MaximumSpinTimeThreshold));
+ if (d == dummyLocked()) {
+ if (timeout == 0)
+ return false;
+ QMutexPrivate *newD = QMutexPrivate::allocate();
+ if (!this->d.testAndSetOrdered(d, newD)) {
+ //Either the mutex is already unlocked, or another thread already set it.
+ newD->deref();
+ continue;
}
+ d = newD;
+ //the d->refCount is already 1 the deref will occurs when we unlock
+ } else if (d->recursive) {
+ return static_cast<QRecursiveMutexPrivate *>(d)->lock(timeout);
+ }
+
+ if (timeout == 0 && !d->possiblyUnlocked)
+ return false;
- // adjust the spin count when spinning does not benefit contention performance
- if ((spinTime + actualWaitTime) - qint64(QMutexPrivate::MaximumSpinTimeThreshold) >= qint64(QMutexPrivate::MaximumSpinTimeThreshold)) {
- // long waits, stop spinning
- d->maximumSpinTime = 0;
- } else {
- // allow spinning if wait times decrease, but never spin more than the average wait time (otherwise we may perform worse)
- d->maximumSpinTime = qBound(qint64(averageWaitTime * 3 / 2), maximumSpinTime / 2, qint64(QMutexPrivate::MaximumSpinTimeThreshold));
+ if (!d->ref())
+ continue; //that QMutexPrivate was already released
+
+ if (d != this->d) {
+ //Either the mutex is already unlocked, or relocked with another mutex
+ d->deref();
+ continue;
+ }
+
+ int old_waiters;
+ do {
+ old_waiters = d->waiters;
+ if (old_waiters == -QMutexPrivate::BigNumber) {
+ // we are unlocking, and the thread that unlocks is about to change d to 0
+ // we try to aquire the mutex by changing to dummyLocked()
+ if (this->d.testAndSetAcquire(d, dummyLocked())) {
+ // Mutex aquired
+ Q_ASSERT(d->waiters == -QMutexPrivate::BigNumber || d->waiters == 0);
+ d->waiters = 0;
+ d->deref();
+ return true;
+ } else {
+ Q_ASSERT(d != this->d); //else testAndSetAcquire should have succeeded
+ // Mutex is likely to bo 0, we should continue the outer-loop,
+ // set old_waiters to the magic value of BigNumber
+ old_waiters = QMutexPrivate::BigNumber;
+ break;
+ }
+ }
+ } while (!d->waiters.testAndSetRelaxed(old_waiters, old_waiters + 1));
+
+ if (d != this->d) {
+ // Mutex was unlocked.
+ if (old_waiters != QMutexPrivate::BigNumber) {
+ //we did not break the previous loop
+ Q_ASSERT(d->waiters >= 1);
+ d->waiters.deref();
}
- return;
+ d->deref();
+ continue;
+ }
+
+ if (d->wait(timeout)) {
+ if (d->possiblyUnlocked && d->possiblyUnlocked.testAndSetRelaxed(true, false))
+ d->deref();
+ d->derefWaiters(1);
+ //we got the lock. (do not deref)
+ Q_ASSERT(d == this->d);
+ return true;
+ } else {
+ Q_ASSERT(timeout >= 0);
+ //timeout
+ d->derefWaiters(1);
+ //There may be a race in which the mutex is unlocked right after we timed out,
+ // and before we deref the waiters, so maybe the mutex is actually unlocked.
+ if (!d->possiblyUnlocked.testAndSetRelaxed(false, true))
+ d->deref();
+ return false;
}
- // be a good citizen... yielding lets something else run if there is something to run, but may also relieve memory pressure if not
- QThread::yieldCurrentThread();
- } while (d->contenders != 0 || !d->contenders.testAndSetAcquire(0, 1));
-
- // spinning is working, do not change the spin time (unless we are using much less time than allowed to spin)
- qint64 maximumSpinTime = d->maximumSpinTime;
- qint64 spinTime = elapsedTimer.nsecsElapsed();
- if (spinTime < maximumSpinTime / 2) {
- // we are using much less time than we need, adjust the limit
- d->maximumSpinTime = qBound(qint64(d->averageWaitTime * 3 / 2), maximumSpinTime / 2, qint64(QMutexPrivate::MaximumSpinTimeThreshold));
}
+ Q_ASSERT(this->d);
+ return true;
}
/*!
\internal
*/
-void QMutex::unlockInternal()
+void QBasicMutex::unlockInternal()
{
- static_cast<QMutexPrivate *>(d)->wakeUp();
+ QMutexPrivate *d = this->d;
+ Q_ASSERT(d); //we must be locked
+ Q_ASSERT(d != dummyLocked()); // testAndSetRelease(dummyLocked(), 0) failed
+
+ if (d->recursive) {
+ static_cast<QRecursiveMutexPrivate *>(d)->unlock();
+ return;
+ }
+
+ if (d->waiters.fetchAndAddRelease(-QMutexPrivate::BigNumber) == 0) {
+ //there is no one waiting on this mutex anymore, set the mutex as unlocked (d = 0)
+ if (this->d.testAndSetRelease(d, 0)) {
+ if (d->possiblyUnlocked && d->possiblyUnlocked.testAndSetRelaxed(true, false))
+ d->deref();
+ }
+ d->derefWaiters(0);
+ } else {
+ d->derefWaiters(0);
+ //there are thread waiting, transfer the lock.
+ d->wakeUp();
+ }
+ d->deref();
}
-/*!
- \fn QMutex::lockInline()
- \internal
- inline version of QMutex::lock()
-*/
+//The freelist managment
+namespace {
+struct FreeListConstants : QFreeListDefaultConstants {
+ enum { BlockCount = 4, MaxIndex=0xffff };
+ static const int Sizes[BlockCount];
+};
+const int FreeListConstants::Sizes[FreeListConstants::BlockCount] = {
+ 16,
+ 128,
+ 1024,
+ FreeListConstants::MaxIndex - (16-128-1024)
+};
+
+typedef QFreeList<QMutexPrivate, FreeListConstants> FreeList;
+Q_GLOBAL_STATIC(FreeList, freelist);
+}
+
+QMutexPrivate *QMutexPrivate::allocate()
+{
+ int i = freelist()->next();
+ QMutexPrivate *d = &(*freelist())[i];
+ d->id = i;
+ Q_ASSERT(d->refCount == 0);
+ Q_ASSERT(!d->recursive);
+ Q_ASSERT(!d->possiblyUnlocked);
+ Q_ASSERT(d->waiters == 0);
+ d->refCount = 1;
+ return d;
+}
+
+void QMutexPrivate::release()
+{
+ Q_ASSERT(!recursive);
+ Q_ASSERT(refCount == 0);
+ Q_ASSERT(!possiblyUnlocked);
+ Q_ASSERT(waiters == 0);
+ freelist()->release(id);
+}
+
+// atomically substract "value" to the waiters, and remove the QMutexPrivate::BigNumber flag
+void QMutexPrivate::derefWaiters(int value)
+{
+ int old_waiters;
+ int new_waiters;
+ do {
+ old_waiters = waiters;
+ new_waiters = old_waiters;
+ if (new_waiters < 0) {
+ new_waiters += QMutexPrivate::BigNumber;
+ }
+ new_waiters -= value;
+ } while (!waiters.testAndSetRelaxed(old_waiters, new_waiters));
+}
+#endif
/*!
- \fn QMutex::unlockInline()
\internal
- inline version of QMutex::unlock()
-*/
+ */
+bool QRecursiveMutexPrivate::lock(int timeout) {
+ Qt::HANDLE self = QThread::currentThreadId();
+ if (owner == self) {
+ ++count;
+ Q_ASSERT_X(count != 0, "QMutex::lock", "Overflow in recursion counter");
+ return true;
+ }
+ bool success = true;
+ if (timeout == -1) {
+ mutex.lock();
+ } else {
+ success = mutex.tryLock(timeout);
+ }
+
+ if (success)
+ owner = self;
+ return success;
+}
/*!
- \fn QMutex::tryLockInline()
\internal
- inline version of QMutex::tryLock()
-*/
+ */
+void QRecursiveMutexPrivate::unlock()
+{
+ if (count > 0) {
+ count--;
+ } else {
+ owner = 0;
+ mutex.unlock();
+ }
+}
QT_END_NAMESPACE
diff --git a/src/corelib/thread/qmutex.h b/src/corelib/thread/qmutex.h
index cc667560db..a49b981d01 100644
--- a/src/corelib/thread/qmutex.h
+++ b/src/corelib/thread/qmutex.h
@@ -52,47 +52,64 @@ QT_BEGIN_NAMESPACE
QT_MODULE(Core)
-#ifndef QT_NO_THREAD
+#if !defined(QT_NO_THREAD) && !defined(qdoc)
-class QAtomicInt;
-class QMutexData;
+class QMutexPrivate;
-class Q_CORE_EXPORT QMutex
+class Q_CORE_EXPORT QBasicMutex
{
- friend class QWaitCondition;
- friend class QWaitConditionPrivate;
-
public:
- enum RecursionMode { NonRecursive, Recursive };
+ inline void lock() {
+ if (!fastTryLock())
+ lockInternal();
+ }
- explicit QMutex(RecursionMode mode = NonRecursive);
- ~QMutex();
+ inline void unlock() {
+ Q_ASSERT(d); //mutex must be locked
+ if (!d.testAndSetRelease(dummyLocked(), 0))
+ unlockInternal();
+ }
+
+ bool tryLock(int timeout = 0) {
+ return fastTryLock() || lockInternal(timeout);
+ }
- void lock(); //### Qt5: make inline;
- inline void lockInline();
- bool tryLock(); //### Qt5: make inline;
- bool tryLock(int timeout);
- inline bool tryLockInline();
- void unlock(); //### Qt5: make inline;
- inline void unlockInline();
+ bool isRecursive();
private:
- void lockInternal();
+ inline bool fastTryLock() {
+ return d.testAndSetAcquire(0, dummyLocked());
+ }
+ bool lockInternal(int timeout = -1);
void unlockInternal();
- Q_DISABLE_COPY(QMutex)
- QMutexData *d;
+ QBasicAtomicPointer<QMutexPrivate> d;
+ static inline QMutexPrivate *dummyLocked() {
+ return reinterpret_cast<QMutexPrivate *>(quintptr(1));
+ }
+
+ friend class QMutex;
+ friend class QMutexPrivate;
+};
+
+class Q_CORE_EXPORT QMutex : public QBasicMutex {
+public:
+ enum RecursionMode { NonRecursive, Recursive };
+ explicit QMutex(RecursionMode mode = NonRecursive);
+ ~QMutex();
+private:
+ Q_DISABLE_COPY(QMutex)
};
class Q_CORE_EXPORT QMutexLocker
{
public:
- inline explicit QMutexLocker(QMutex *m)
+ inline explicit QMutexLocker(QBasicMutex *m)
{
Q_ASSERT_X((reinterpret_cast<quintptr>(m) & quintptr(1u)) == quintptr(0),
"QMutexLocker", "QMutex pointer is misaligned");
if (m) {
- m->lockInline();
+ m->lock();
val = reinterpret_cast<quintptr>(m) | quintptr(1u);
} else {
val = 0;
@@ -104,7 +121,7 @@ public:
{
if ((val & quintptr(1u)) == quintptr(1u)) {
val &= ~quintptr(1u);
- mutex()->unlockInline();
+ mutex()->unlock();
}
}
@@ -112,7 +129,7 @@ public:
{
if (val) {
if ((val & quintptr(1u)) == quintptr(0u)) {
- mutex()->lockInline();
+ mutex()->lock();
val |= quintptr(1u);
}
}
@@ -138,54 +155,9 @@ private:
quintptr val;
};
-class QMutexData
-{
- public:
- QAtomicInt contenders;
- const uint recursive : 1;
- uint reserved : 31;
- protected:
- QMutexData(QMutex::RecursionMode mode);
- ~QMutexData();
-};
-
-#ifdef QT_NO_DEBUG
-inline void QMutex::unlockInline()
-{
- if (d->recursive) {
- unlock();
- } else if (!d->contenders.testAndSetRelease(1, 0)) {
- unlockInternal();
- }
-}
-
-inline bool QMutex::tryLockInline()
-{
- if (d->recursive) {
- return tryLock();
- } else {
- return d->contenders.testAndSetAcquire(0, 1);
- }
-}
-
-inline void QMutex::lockInline()
-{
- if (d->recursive) {
- lock();
- } else if(!tryLockInline()) {
- lockInternal();
- }
-}
-#else // QT_NO_DEBUG
-//in debug we do not use inline calls in order to allow debugging tools
-// to hook the mutex locking functions.
-inline void QMutex::unlockInline() { unlock(); }
-inline bool QMutex::tryLockInline() { return tryLock(); }
-inline void QMutex::lockInline() { lock(); }
-#endif // QT_NO_DEBUG
-#else // QT_NO_THREAD
+#else // QT_NO_THREAD or qdoc
class Q_CORE_EXPORT QMutex
@@ -194,14 +166,11 @@ public:
enum RecursionMode { NonRecursive, Recursive };
inline explicit QMutex(RecursionMode mode = NonRecursive) { Q_UNUSED(mode); }
- inline ~QMutex() {}
static inline void lock() {}
- static inline void lockInline() {}
static inline bool tryLock(int timeout = 0) { Q_UNUSED(timeout); return true; }
- static inline bool tryLockInline() { return true; }
static inline void unlock() {}
- static inline void unlockInline() {}
+ static inline bool isRecursive() { return true; }
private:
Q_DISABLE_COPY(QMutex)
@@ -221,7 +190,9 @@ private:
Q_DISABLE_COPY(QMutexLocker)
};
-#endif // QT_NO_THREAD
+typedef QMutex QBasicMutex;
+
+#endif // QT_NO_THREAD or qdoc
QT_END_NAMESPACE
diff --git a/src/corelib/thread/qmutex_linux.cpp b/src/corelib/thread/qmutex_linux.cpp
new file mode 100644
index 0000000000..17015b8f84
--- /dev/null
+++ b/src/corelib/thread/qmutex_linux.cpp
@@ -0,0 +1,138 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qplatformdefs.h"
+#include "qmutex.h"
+
+#ifndef QT_NO_THREAD
+#include "qatomic.h"
+#include "qmutex_p.h"
+# include "qelapsedtimer.h"
+
+#include <linux/futex.h>
+#include <sys/syscall.h>
+#include <unistd.h>
+#include <errno.h>
+
+QT_BEGIN_NAMESPACE
+
+static inline int _q_futex(QMutexPrivate *volatile *addr, int op, int val, const struct timespec *timeout)
+{
+ volatile int *int_addr = reinterpret_cast<volatile int *>(addr);
+#if Q_BYTE_ORDER == Q_BIG_ENDIAN && QT_POINTER_SIZE == 8
+ int_addr++; //We want a pointer to the 32 least significant bit of QMutex::d
+#endif
+ int *addr2 = 0;
+ int val2 = 0;
+ return syscall(SYS_futex, int_addr, op, val, timeout, addr2, val2);
+}
+
+static inline QMutexPrivate *dummyFutexValue()
+{
+ return reinterpret_cast<QMutexPrivate *>(quintptr(3));
+}
+
+
+QMutexPrivate::~QMutexPrivate() {}
+QMutexPrivate::QMutexPrivate(QMutex::RecursionMode mode)
+ : recursive(mode == QMutex::Recursive) {}
+
+bool QBasicMutex::lockInternal(int timeout)
+{
+ QElapsedTimer elapsedTimer;
+ if (timeout >= 1)
+ elapsedTimer.start();
+
+ while (!fastTryLock()) {
+ QMutexPrivate *d = this->d;
+ if (!d) // if d is 0, the mutex is unlocked
+ continue;
+
+ if (quintptr(d) <= 0x3) { //d == dummyLocked() || d == dummyFutexValue()
+ if (timeout == 0)
+ return false;
+ while (this->d.fetchAndStoreAcquire(dummyFutexValue()) != 0) {
+ struct timespec ts, *pts = 0;
+ if (timeout >= 1) {
+ // recalculate the timeout
+ qint64 xtimeout = timeout * 1000 * 1000;
+ xtimeout -= elapsedTimer.nsecsElapsed();
+ if (xtimeout <= 0) {
+ // timer expired after we returned
+ return false;
+ }
+ ts.tv_sec = xtimeout / Q_INT64_C(1000) / 1000 / 1000;
+ ts.tv_nsec = xtimeout % (Q_INT64_C(1000) * 1000 * 1000);
+ pts = &ts;
+ }
+ int r = _q_futex(&this->d._q_value, FUTEX_WAIT, quintptr(dummyFutexValue()), pts);
+ if (r != 0 && errno == ETIMEDOUT)
+ return false;
+ }
+ return true;
+ }
+ Q_ASSERT(d->recursive);
+ return static_cast<QRecursiveMutexPrivate *>(d)->lock(timeout);
+ }
+ Q_ASSERT(this->d);
+ return true;
+}
+
+void QBasicMutex::unlockInternal()
+{
+ QMutexPrivate *d = this->d;
+ Q_ASSERT(d); //we must be locked
+ Q_ASSERT(d != dummyLocked()); // testAndSetRelease(dummyLocked(), 0) failed
+
+ if (d == dummyFutexValue()) {
+ this->d.fetchAndStoreRelease(0);
+ _q_futex(&this->d._q_value, FUTEX_WAKE, 1, 0);
+ return;
+ }
+
+ Q_ASSERT(d->recursive);
+ static_cast<QRecursiveMutexPrivate *>(d)->unlock();
+}
+
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_THREAD
diff --git a/src/corelib/thread/qmutex_mac.cpp b/src/corelib/thread/qmutex_mac.cpp
new file mode 100644
index 0000000000..f63feebca4
--- /dev/null
+++ b/src/corelib/thread/qmutex_mac.cpp
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qplatformdefs.h"
+#include "qmutex.h"
+
+#if !defined(QT_NO_THREAD)
+
+#include "qmutex_p.h"
+
+#include <mach/mach.h>
+#include <mach/task.h>
+
+#include <errno.h>
+
+QT_BEGIN_NAMESPACE
+
+QMutexPrivate::QMutexPrivate(QMutex::RecursionMode mode)
+ : recursive(mode == QMutex::Recursive)
+{
+ kern_return_t r = semaphore_create(mach_task_self(), &mach_semaphore, SYNC_POLICY_FIFO, 0);
+ if (r != KERN_SUCCESS)
+ qWarning("QMutex: failed to create semaphore, error %d", r);
+}
+
+QMutexPrivate::~QMutexPrivate()
+{
+ kern_return_t r = semaphore_destroy(mach_task_self(), mach_semaphore);
+ if (r != KERN_SUCCESS)
+ qWarning("QMutex: failed to destroy semaphore, error %d", r);
+}
+
+bool QMutexPrivate::wait(int timeout)
+{
+ kern_return_t r;
+ if (timeout < 0) {
+ do {
+ r = semaphore_wait(mach_semaphore);
+ } while (r == KERN_ABORTED);
+ Q_ASSERT(r == KERN_SUCCESS);
+ } else {
+ mach_timespec_t ts;
+ ts.tv_nsec = ((timeout % 1000) * 1000) * 1000;
+ ts.tv_sec = (timeout / 1000);
+ r = semaphore_timedwait(mach_semaphore, ts);
+ }
+ return (r == KERN_SUCCESS);
+}
+
+void QMutexPrivate::wakeUp()
+{
+ semaphore_signal(mach_semaphore);
+}
+
+
+QT_END_NAMESPACE
+
+#endif //QT_NO_THREAD
diff --git a/src/corelib/thread/qmutex_p.h b/src/corelib/thread/qmutex_p.h
index a9923c47a4..00f071ebef 100644
--- a/src/corelib/thread/qmutex_p.h
+++ b/src/corelib/thread/qmutex_p.h
@@ -57,50 +57,80 @@
#include <QtCore/qglobal.h>
#include <QtCore/qnamespace.h>
#include <QtCore/qmutex.h>
+#include <QtCore/qatomic.h>
#if defined(Q_OS_MAC)
# include <mach/semaphore.h>
#endif
-#if defined(Q_OS_SYMBIAN)
-# include <e32std.h>
-#endif
-
QT_BEGIN_NAMESPACE
-class QMutexPrivate : public QMutexData {
+class QMutexPrivate {
public:
- QMutexPrivate(QMutex::RecursionMode mode);
~QMutexPrivate();
+ QMutexPrivate(QMutex::RecursionMode mode = QMutex::NonRecursive);
bool wait(int timeout = -1);
void wakeUp();
- // 1ms = 1000000ns
- enum { MaximumSpinTimeThreshold = 1000000 };
- volatile qint64 maximumSpinTime;
- volatile qint64 averageWaitTime;
- Qt::HANDLE owner;
- uint count;
+#if !defined(Q_OS_LINUX)
+ // Conrol the lifetime of the privates
+ QAtomicInt refCount;
+ int id;
+
+ bool ref() {
+ Q_ASSERT(refCount >= 0);
+ int c;
+ do {
+ c = refCount;
+ if (c == 0)
+ return false;
+ } while (!refCount.testAndSetRelaxed(c, c + 1));
+ Q_ASSERT(refCount >= 0);
+ return true;
+ }
+ void deref() {
+ Q_ASSERT(refCount >=0);
+ if (!refCount.deref())
+ release();
+ Q_ASSERT(refCount >=0);
+ }
+ void release();
+ static QMutexPrivate *allocate();
+
+ QAtomicInt waiters; //number of thread waiting
+ QAtomicInt possiblyUnlocked; //bool saying that a timed wait timed out
+ enum { BigNumber = 0x100000 }; //Must be bigger than the possible number of waiters (number of threads)
+ void derefWaiters(int value);
+#endif
+
+ // handle recursive mutex
+ bool recursive;
+ //platform specific stuff
#if defined(Q_OS_MAC)
semaphore_t mach_semaphore;
-#elif defined(Q_OS_UNIX) && !defined(Q_OS_LINUX) && !defined(Q_OS_SYMBIAN)
- volatile bool wakeup;
+#elif defined(Q_OS_UNIX) && !defined(Q_OS_LINUX)
+ bool wakeup;
pthread_mutex_t mutex;
pthread_cond_t cond;
#elif defined(Q_OS_WIN32) || defined(Q_OS_WINCE)
HANDLE event;
-#elif defined(Q_OS_SYMBIAN)
- RSemaphore lock;
#endif
};
-inline QMutexData::QMutexData(QMutex::RecursionMode mode)
- : recursive(mode == QMutex::Recursive)
-{}
+class QRecursiveMutexPrivate : public QMutexPrivate
+{
+public:
+ QRecursiveMutexPrivate()
+ : QMutexPrivate(QMutex::Recursive), owner(0), count(0) {}
+ Qt::HANDLE owner;
+ uint count;
+ QMutex mutex;
-inline QMutexData::~QMutexData() {}
+ bool lock(int timeout);
+ void unlock();
+};
QT_END_NAMESPACE
diff --git a/src/corelib/thread/qmutex_unix.cpp b/src/corelib/thread/qmutex_unix.cpp
index e692e19525..0bccad589d 100644
--- a/src/corelib/thread/qmutex_unix.cpp
+++ b/src/corelib/thread/qmutex_unix.cpp
@@ -46,142 +46,35 @@
#ifndef QT_NO_THREAD
#include "qatomic.h"
#include "qmutex_p.h"
-
#include <errno.h>
#if defined(Q_OS_VXWORKS) && defined(wakeup)
#undef wakeup
#endif
-#if defined(Q_OS_MAC)
-# include <mach/mach.h>
-# include <mach/task.h>
-#elif defined(Q_OS_LINUX)
-# include <linux/futex.h>
-# include <sys/syscall.h>
-# include <unistd.h>
-# include <QtCore/qelapsedtimer.h>
-#endif
-
QT_BEGIN_NAMESPACE
-#if !defined(Q_OS_MAC) && !defined(Q_OS_LINUX)
static void report_error(int code, const char *where, const char *what)
{
if (code != 0)
qWarning("%s: %s failure: %s", where, what, qPrintable(qt_error_string(code)));
}
-#endif
-
QMutexPrivate::QMutexPrivate(QMutex::RecursionMode mode)
- : QMutexData(mode), maximumSpinTime(MaximumSpinTimeThreshold), averageWaitTime(0), owner(0), count(0)
+ : recursive(mode == QMutex::Recursive), wakeup(false)
{
-#if defined(Q_OS_MAC)
- kern_return_t r = semaphore_create(mach_task_self(), &mach_semaphore, SYNC_POLICY_FIFO, 0);
- if (r != KERN_SUCCESS)
- qWarning("QMutex: failed to create semaphore, error %d", r);
-#elif !defined(Q_OS_LINUX)
- wakeup = false;
report_error(pthread_mutex_init(&mutex, NULL), "QMutex", "mutex init");
report_error(pthread_cond_init(&cond, NULL), "QMutex", "cv init");
-#endif
}
QMutexPrivate::~QMutexPrivate()
{
-#if defined(Q_OS_MAC)
- kern_return_t r = semaphore_destroy(mach_task_self(), mach_semaphore);
- if (r != KERN_SUCCESS)
- qWarning("QMutex: failed to destroy semaphore, error %d", r);
-#elif !defined(Q_OS_LINUX)
report_error(pthread_cond_destroy(&cond), "QMutex", "cv destroy");
report_error(pthread_mutex_destroy(&mutex), "QMutex", "mutex destroy");
-#endif
}
-#if defined(Q_OS_MAC)
-
bool QMutexPrivate::wait(int timeout)
{
- if (contenders.fetchAndAddAcquire(1) == 0) {
- // lock acquired without waiting
- return true;
- }
- kern_return_t r;
- if (timeout < 0) {
- do {
- r = semaphore_wait(mach_semaphore);
- } while (r == KERN_ABORTED);
- if (r != KERN_SUCCESS)
- qWarning("QMutex: infinite wait failed, error %d", r);
- } else {
- mach_timespec_t ts;
- ts.tv_nsec = ((timeout % 1000) * 1000) * 1000;
- ts.tv_sec = (timeout / 1000);
- r = semaphore_timedwait(mach_semaphore, ts);
- }
- contenders.deref();
- return r == KERN_SUCCESS;
-}
-
-void QMutexPrivate::wakeUp()
-{
- semaphore_signal(mach_semaphore);
-}
-
-#elif defined(Q_OS_LINUX)
-
-static inline int _q_futex(volatile int *addr, int op, int val, const struct timespec *timeout, int *addr2, int val2)
-{
- return syscall(SYS_futex, addr, op, val, timeout, addr2, val2);
-}
-
-bool QMutexPrivate::wait(int timeout)
-{
- struct timespec ts, *pts = 0;
- QElapsedTimer timer;
- if (timeout >= 0) {
- ts.tv_nsec = ((timeout % 1000) * 1000) * 1000;
- ts.tv_sec = (timeout / 1000);
- pts = &ts;
- timer.start();
- }
- while (contenders.fetchAndStoreAcquire(2) > 0) {
- int r = _q_futex(&contenders._q_value, FUTEX_WAIT, 2, pts, 0, 0);
- if (r != 0 && errno == ETIMEDOUT)
- return false;
-
- if (pts) {
- // recalculate the timeout
- qint64 xtimeout = timeout * 1000 * 1000;
- xtimeout -= timer.nsecsElapsed();
- if (xtimeout < 0) {
- // timer expired after we returned
- return false;
- }
-
- ts.tv_sec = timeout / Q_INT64_C(1000) / 1000 / 1000;
- ts.tv_nsec = timeout % (Q_INT64_C(1000) * 1000 * 1000);
- }
- }
- return true;
-}
-
-void QMutexPrivate::wakeUp()
-{
- (void) contenders.fetchAndStoreRelease(0);
- (void) _q_futex(&contenders._q_value, FUTEX_WAKE, 1, 0, 0, 0);
-}
-
-#else // !Q_OS_MAC && !Q_OS_LINUX
-
-bool QMutexPrivate::wait(int timeout)
-{
- if (contenders.fetchAndAddAcquire(1) == 0) {
- // lock acquired without waiting
- return true;
- }
report_error(pthread_mutex_lock(&mutex), "QMutex::lock", "mutex lock");
int errorCode = 0;
while (!wakeup) {
@@ -190,12 +83,10 @@ bool QMutexPrivate::wait(int timeout)
} else {
struct timeval tv;
gettimeofday(&tv, 0);
-
timespec ti;
ti.tv_nsec = (tv.tv_usec + (timeout % 1000) * 1000) * 1000;
ti.tv_sec = tv.tv_sec + (timeout / 1000) + (ti.tv_nsec / 1000000000);
ti.tv_nsec %= 1000000000;
-
errorCode = pthread_cond_timedwait(&cond, &mutex, &ti);
}
if (errorCode) {
@@ -207,10 +98,10 @@ bool QMutexPrivate::wait(int timeout)
report_error(errorCode, "QMutex::lock()", "cv wait");
}
}
+ bool ret = wakeup;
wakeup = false;
report_error(pthread_mutex_unlock(&mutex), "QMutex::lock", "mutex unlock");
- contenders.deref();
- return errorCode == 0;
+ return ret;
}
void QMutexPrivate::wakeUp()
@@ -221,7 +112,6 @@ void QMutexPrivate::wakeUp()
report_error(pthread_mutex_unlock(&mutex), "QMutex::unlock", "mutex unlock");
}
-#endif // !Q_OS_MAC && !Q_OS_LINUX
QT_END_NAMESPACE
diff --git a/src/corelib/thread/qmutex_win.cpp b/src/corelib/thread/qmutex_win.cpp
index 53ad8cfe89..f6670f6d1e 100644
--- a/src/corelib/thread/qmutex_win.cpp
+++ b/src/corelib/thread/qmutex_win.cpp
@@ -48,7 +48,7 @@
QT_BEGIN_NAMESPACE
QMutexPrivate::QMutexPrivate(QMutex::RecursionMode mode)
- : QMutexData(mode), maximumSpinTime(MaximumSpinTimeThreshold), averageWaitTime(0), owner(0), count(0)
+ : recursive(mode)
{
event = CreateEvent(0, FALSE, FALSE, 0);
if (!event)
@@ -60,13 +60,7 @@ QMutexPrivate::~QMutexPrivate()
bool QMutexPrivate::wait(int timeout)
{
- if (contenders.fetchAndAddAcquire(1) == 0) {
- // lock acquired without waiting
- return true;
- }
- bool returnValue = (WaitForSingleObject(event, timeout < 0 ? INFINITE : timeout) == WAIT_OBJECT_0);
- contenders.deref();
- return returnValue;
+ return (WaitForSingleObject(event, timeout < 0 ? INFINITE : timeout) == WAIT_OBJECT_0);
}
void QMutexPrivate::wakeUp()
diff --git a/src/corelib/thread/qorderedmutexlocker_p.h b/src/corelib/thread/qorderedmutexlocker_p.h
index 8f01c1c056..e65a601369 100644
--- a/src/corelib/thread/qorderedmutexlocker_p.h
+++ b/src/corelib/thread/qorderedmutexlocker_p.h
@@ -79,8 +79,8 @@ public:
void relock()
{
if (!locked) {
- if (mtx1) mtx1->lockInline();
- if (mtx2) mtx2->lockInline();
+ if (mtx1) mtx1->lock();
+ if (mtx2) mtx2->lock();
locked = true;
}
}
@@ -88,8 +88,8 @@ public:
void unlock()
{
if (locked) {
- if (mtx1) mtx1->unlockInline();
- if (mtx2) mtx2->unlockInline();
+ if (mtx1) mtx1->unlock();
+ if (mtx2) mtx2->unlock();
locked = false;
}
}
@@ -100,10 +100,10 @@ public:
if (mtx1 == mtx2)
return false;
if (mtx1 < mtx2) {
- mtx2->lockInline();
+ mtx2->lock();
return true;
}
- if (!mtx2->tryLockInline()) {
+ if (!mtx2->tryLock()) {
mtx1->unlock();
mtx2->lock();
mtx1->lock();
diff --git a/src/corelib/thread/qwaitcondition_unix.cpp b/src/corelib/thread/qwaitcondition_unix.cpp
index b946a9de24..dd85bf4023 100644
--- a/src/corelib/thread/qwaitcondition_unix.cpp
+++ b/src/corelib/thread/qwaitcondition_unix.cpp
@@ -146,7 +146,7 @@ bool QWaitCondition::wait(QMutex *mutex, unsigned long time)
{
if (! mutex)
return false;
- if (mutex->d->recursive) {
+ if (mutex->isRecursive()) {
qWarning("QWaitCondition: cannot wait on recursive mutexes");
return false;
}
diff --git a/src/corelib/thread/qwaitcondition_win.cpp b/src/corelib/thread/qwaitcondition_win.cpp
index 8a8db97342..bf1ec5e5ba 100644
--- a/src/corelib/thread/qwaitcondition_win.cpp
+++ b/src/corelib/thread/qwaitcondition_win.cpp
@@ -164,7 +164,7 @@ bool QWaitCondition::wait(QMutex *mutex, unsigned long time)
{
if (!mutex)
return false;
- if (mutex->d->recursive) {
+ if (mutex->isRecursive()) {
qWarning("QWaitCondition::wait: Cannot wait on recursive mutexes");
return false;
}
diff --git a/src/corelib/thread/thread.pri b/src/corelib/thread/thread.pri
index 592ab1644b..309bf30d25 100644
--- a/src/corelib/thread/thread.pri
+++ b/src/corelib/thread/thread.pri
@@ -24,8 +24,7 @@ SOURCES += thread/qatomic.cpp \
thread/qthread.cpp \
thread/qthreadstorage.cpp
-unix:!symbian:SOURCES += thread/qmutex_unix.cpp \
- thread/qthread_unix.cpp \
+unix:!symbian:SOURCES += thread/qthread_unix.cpp \
thread/qwaitcondition_unix.cpp
symbian:SOURCES += thread/qmutex_symbian.cpp \
@@ -39,3 +38,9 @@ win32:SOURCES += thread/qmutex_win.cpp \
integrity:SOURCES += thread/qmutex_unix.cpp \
thread/qthread_unix.cpp \
thread/qwaitcondition_unix.cpp
+
+unix: {
+ macx-* { SOURCES += thread/qmutex_mac.cpp }
+ else:linux-* { SOURCES += thread/qmutex_linux.cpp }
+ else { SOURCES += thread/qmutex_unix.cpp }
+}
diff --git a/src/corelib/tools/qbytearray.cpp b/src/corelib/tools/qbytearray.cpp
index 9f21b72bfd..11ebd8a103 100644
--- a/src/corelib/tools/qbytearray.cpp
+++ b/src/corelib/tools/qbytearray.cpp
@@ -904,7 +904,7 @@ QByteArray &QByteArray::operator=(const char *str)
x = const_cast<Data *>(&shared_empty.ba);
} else {
int len = qstrlen(str);
- if (d->ref != 1 || len > d->alloc || (len < d->size && len < d->alloc >> 1))
+ if (d->ref != 1 || len > int(d->alloc) || (len < d->size && len < int(d->alloc) >> 1))
realloc(len);
x = d;
memcpy(x->data(), str, len + 1); // include null terminator
@@ -1432,9 +1432,10 @@ void QByteArray::resize(int size)
x->data()[size] = '\0';
d = x;
} else {
- if (d->ref != 1 || size > d->alloc || (!d->capacityReserved && size < d->size && size < d->alloc >> 1))
+ if (d->ref != 1 || size > int(d->alloc)
+ || (!d->capacityReserved && size < d->size && size < int(d->alloc) >> 1))
realloc(qAllocMore(size, sizeof(Data)));
- if (d->alloc >= size) {
+ if (int(d->alloc) >= size) {
d->size = size;
d->data()[size] = '\0';
}
@@ -1563,7 +1564,7 @@ QByteArray &QByteArray::prepend(const char *str)
QByteArray &QByteArray::prepend(const char *str, int len)
{
if (str) {
- if (d->ref != 1 || d->size + len > d->alloc)
+ if (d->ref != 1 || d->size + len > int(d->alloc))
realloc(qAllocMore(d->size + len, sizeof(Data)));
memmove(d->data()+len, d->data(), d->size);
memcpy(d->data(), str, len);
@@ -1581,7 +1582,7 @@ QByteArray &QByteArray::prepend(const char *str, int len)
QByteArray &QByteArray::prepend(char ch)
{
- if (d->ref != 1 || d->size + 1 > d->alloc)
+ if (d->ref != 1 || d->size + 1 > int(d->alloc))
realloc(qAllocMore(d->size + 1, sizeof(Data)));
memmove(d->data()+1, d->data(), d->size);
d->data()[0] = ch;
@@ -1619,7 +1620,7 @@ QByteArray &QByteArray::append(const QByteArray &ba)
if ((d == &shared_null.ba || d == &shared_empty.ba) && !IS_RAW_DATA(ba.d)) {
*this = ba;
} else if (ba.d != &shared_null.ba) {
- if (d->ref != 1 || d->size + ba.d->size > d->alloc)
+ if (d->ref != 1 || d->size + ba.d->size > int(d->alloc))
realloc(qAllocMore(d->size + ba.d->size, sizeof(Data)));
memcpy(d->data() + d->size, ba.d->data(), ba.d->size);
d->size += ba.d->size;
@@ -1653,7 +1654,7 @@ QByteArray& QByteArray::append(const char *str)
{
if (str) {
int len = qstrlen(str);
- if (d->ref != 1 || d->size + len > d->alloc)
+ if (d->ref != 1 || d->size + len > int(d->alloc))
realloc(qAllocMore(d->size + len, sizeof(Data)));
memcpy(d->data() + d->size, str, len + 1); // include null terminator
d->size += len;
@@ -1678,7 +1679,7 @@ QByteArray &QByteArray::append(const char *str, int len)
if (len < 0)
len = qstrlen(str);
if (str && len) {
- if (d->ref != 1 || d->size + len > d->alloc)
+ if (d->ref != 1 || d->size + len > int(d->alloc))
realloc(qAllocMore(d->size + len, sizeof(Data)));
memcpy(d->data() + d->size, str, len); // include null terminator
d->size += len;
@@ -1695,7 +1696,7 @@ QByteArray &QByteArray::append(const char *str, int len)
QByteArray& QByteArray::append(char ch)
{
- if (d->ref != 1 || d->size + 1 > d->alloc)
+ if (d->ref != 1 || d->size + 1 > int(d->alloc))
realloc(qAllocMore(d->size + 1, sizeof(Data)));
d->data()[d->size++] = ch;
d->data()[d->size] = '\0';
@@ -2204,7 +2205,7 @@ QByteArray QByteArray::repeated(int times) const
QByteArray result;
result.reserve(resultSize);
- if (result.d->alloc != resultSize)
+ if (int(result.d->alloc) != resultSize)
return QByteArray(); // not enough memory
memcpy(result.d->data(), d->data(), d->size);
diff --git a/src/corelib/tools/qbytearray.h b/src/corelib/tools/qbytearray.h
index dbac302d05..b70dba4d55 100644
--- a/src/corelib/tools/qbytearray.h
+++ b/src/corelib/tools/qbytearray.h
@@ -133,10 +133,10 @@ struct QByteArrayData
inline const char *data() const { return d + sizeof(qptrdiff) + offset; }
};
-template<int n> struct QConstByteArrayData
+template<int N> struct QConstByteArrayData
{
const QByteArrayData ba;
- const char data[n];
+ const char data[N + 1];
};
template<int N> struct QConstByteArrayDataPtr
@@ -146,10 +146,10 @@ template<int N> struct QConstByteArrayDataPtr
#if defined(Q_COMPILER_LAMBDA)
-# define QByteArrayLiteral(str) ([]() { \
- enum { Size = sizeof(str) }; \
+# define QByteArrayLiteral(str) ([]() -> QConstByteArrayDataPtr<sizeof(str) - 1> { \
+ enum { Size = sizeof(str) - 1 }; \
static const QConstByteArrayData<Size> qbytearray_literal = \
- { { Q_REFCOUNT_INITIALIZER(-1), Size -1, 0, 0, { 0 } }, str }; \
+ { { Q_REFCOUNT_INITIALIZER(-1), Size, 0, 0, { 0 } }, str }; \
QConstByteArrayDataPtr<Size> holder = { &qbytearray_literal }; \
return holder; }())
@@ -160,9 +160,9 @@ template<int N> struct QConstByteArrayDataPtr
# define QByteArrayLiteral(str) \
__extension__ ({ \
- enum { Size = sizeof(str) }; \
+ enum { Size = sizeof(str) - 1 }; \
static const QConstByteArrayData<Size> qbytearray_literal = \
- { { Q_REFCOUNT_INITIALIZER(-1), Size -1, 0, 0, { 0 } }, str }; \
+ { { Q_REFCOUNT_INITIALIZER(-1), Size, 0, 0, { 0 } }, str }; \
QConstByteArrayDataPtr<Size> holder = { &qbytearray_literal }; \
holder; })
#endif
@@ -439,10 +439,10 @@ inline int QByteArray::capacity() const
{ return d->alloc; }
inline void QByteArray::reserve(int asize)
-{ if (d->ref != 1 || asize > d->alloc) realloc(asize); d->capacityReserved = true; }
+{ if (d->ref != 1 || asize > int(d->alloc)) realloc(asize); d->capacityReserved = true; }
inline void QByteArray::squeeze()
-{ if (d->size < d->alloc) realloc(d->size); d->capacityReserved = false; }
+{ if (d->size < int(d->alloc)) realloc(d->size); d->capacityReserved = false; }
class Q_CORE_EXPORT QByteRef {
QByteArray &a;
diff --git a/src/corelib/tools/qchar.cpp b/src/corelib/tools/qchar.cpp
index 00261daa95..736bc63b11 100644
--- a/src/corelib/tools/qchar.cpp
+++ b/src/corelib/tools/qchar.cpp
@@ -317,8 +317,6 @@ QT_BEGIN_NAMESPACE
\value Vertical
\value Wide
- \omitvalue Single
-
\sa decomposition()
*/
@@ -382,12 +380,6 @@ QT_BEGIN_NAMESPACE
\value ByteOrderSwapped
\value ParagraphSeparator
\value LineSeparator
-
- \omitvalue null
- \omitvalue replacement
- \omitvalue byteOrderMark
- \omitvalue byteOrderSwapped
- \omitvalue nbsp
*/
/*!
@@ -957,7 +949,7 @@ QString QChar::decomposition(uint ucs4)
/*!
Returns the tag defining the composition of the character. Returns
- QChar::Single if no decomposition exists.
+ QChar::NoDecomposition if no decomposition exists.
*/
QChar::Decomposition QChar::decompositionTag() const
{
@@ -967,7 +959,7 @@ QChar::Decomposition QChar::decompositionTag() const
/*!
\overload
Returns the tag defining the composition of the UCS-4-encoded character
- specified by \a ucs4. Returns QChar::Single if no decomposition exists.
+ specified by \a ucs4. Returns QChar::NoDecomposition if no decomposition exists.
*/
QChar::Decomposition QChar::decompositionTag(uint ucs4)
{
@@ -1232,7 +1224,6 @@ ushort QChar::toCaseFolded(ushort ucs2)
return ucs2 + qGetProp(ucs2)->caseFoldDiff;
}
-
/*!
\fn char QChar::toLatin1() const
diff --git a/src/corelib/tools/qfreelist.cpp b/src/corelib/tools/qfreelist.cpp
new file mode 100644
index 0000000000..bbbdb25e49
--- /dev/null
+++ b/src/corelib/tools/qfreelist.cpp
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfreelist_p.h"
+
+QT_BEGIN_NAMESPACE
+
+// default sizes and offsets (no need to define these when customizing)
+enum {
+ Offset0 = 0x00000000,
+ Offset1 = 0x00008000,
+ Offset2 = 0x00080000,
+ Offset3 = 0x00800000,
+
+ Size0 = Offset1 - Offset0,
+ Size1 = Offset2 - Offset1,
+ Size2 = Offset3 - Offset2,
+ Size3 = QFreeListDefaultConstants::MaxIndex - Offset3
+};
+
+const int QFreeListDefaultConstants::Sizes[QFreeListDefaultConstants::BlockCount] = {
+ Size0,
+ Size1,
+ Size2,
+ Size3
+};
+
+QT_END_NAMESPACE
+
diff --git a/src/corelib/tools/qfreelist_p.h b/src/corelib/tools/qfreelist_p.h
new file mode 100644
index 0000000000..74ba3b587e
--- /dev/null
+++ b/src/corelib/tools/qfreelist_p.h
@@ -0,0 +1,294 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFREELIST_P_H
+#define QFREELIST_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qatomic.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+/*! \internal
+
+ Element in a QFreeList. ConstReferenceType and ReferenceType are used as
+ the return values for QFreeList::at() and QFreeList::operator[](). Contains
+ the real data storage (_t) and the id of the next free element (next).
+
+ Note: the t() functions should be used to access the data, not _t.
+*/
+template <typename T>
+struct QFreeListElement
+{
+ typedef const T &ConstReferenceType;
+ typedef T &ReferenceType;
+
+ T _t;
+ int next;
+
+ inline ConstReferenceType t() const { return _t; }
+ inline ReferenceType t() { return _t; }
+};
+
+/*! \internal
+
+ Element in a QFreeList without a paylout. ConstReferenceType and
+ ReferenceType are void, the t() functions return void and are empty.
+*/
+template <>
+struct QFreeListElement<void>
+{
+ typedef void ConstReferenceType;
+ typedef void ReferenceType;
+
+ int next;
+
+ inline void t() const { }
+ inline void t() { }
+};
+
+/*! \internal
+
+ Defines default constants used by QFreeList:
+
+ - The initial value returned by QFreeList::next() is zero.
+
+ - QFreeList allows for up to 16777216 elements in QFreeList and uses the top
+ 8 bits to store a serial counter for ABA protection.
+
+ - QFreeList will make a maximum of 4 allocations (blocks), with each
+ successive block larger than the previous.
+
+ - Sizes static int[] array to define the size of each block.
+
+ It is possible to define your own constants struct/class and give this to
+ QFreeList to customize/tune the behavior.
+*/
+struct Q_AUTOTEST_EXPORT QFreeListDefaultConstants
+{
+ // used by QFreeList, make sure to define all of when customizing
+ enum {
+ InitialNextValue = 0,
+ IndexMask = 0x00ffffff,
+ SerialMask = ~IndexMask & ~0x80000000,
+ SerialCounter = IndexMask + 1,
+ MaxIndex = IndexMask,
+ BlockCount = 4,
+ };
+
+ static const int Sizes[BlockCount];
+};
+
+/*! \internal
+
+ This is a generic implementation of a lock-free free list. Use next() to
+ get the next free entry in the list, and release(id) when done with the id.
+
+ This version is templated and allows having a payload of type T which can
+ be accessed using the id returned by next(). The payload is allocated and
+ deallocated automatically by the free list, but *NOT* when calling
+ next()/release(). Initialization should be done by code needing it after
+ next() returns. Likewise, cleanup() should happen before calling release().
+ It is possible to have use 'void' as the payload type, in which case the
+ free list only contains indexes to the next free entry.
+
+ The ConstantsType type defaults to QFreeListDefaultConstants above. You can
+ define your custom ConstantsType, see above for details on what needs to be
+ available.
+*/
+template <typename T, typename ConstantsType = QFreeListDefaultConstants>
+class QFreeList
+{
+ typedef T ValueType;
+ typedef QFreeListElement<T> ElementType;
+ typedef typename ElementType::ConstReferenceType ConstReferenceType;
+ typedef typename ElementType::ReferenceType ReferenceType;
+
+ // return which block the index \a x falls in, and modify \a x to be the index into that block
+ static inline int blockfor(int &x)
+ {
+ for (int i = 0; i < ConstantsType::BlockCount; ++i) {
+ int size = ConstantsType::Sizes[i];
+ if (x < size)
+ return i;
+ x -= size;
+ }
+ Q_ASSERT(false);
+ return -1;
+ }
+
+ // allocate a block of the given \a size, initialized starting with the given \a offset
+ static inline ElementType *allocate(int offset, int size)
+ {
+ // qDebug("QFreeList: allocating %d elements (%ld bytes) with offset %d", size, size * sizeof(ElementType), offset);
+ ElementType *v = new ElementType[size];
+ for (int i = 0; i < size; ++i)
+ v[i].next = offset + i + 1;
+ return v;
+ }
+
+ // take the current serial number from \a o, increment it, and store it in \a n
+ static inline int incrementserial(int o, int n)
+ {
+ return (n & ConstantsType::IndexMask) | ((o + ConstantsType::SerialCounter) & ConstantsType::SerialMask);
+ }
+
+ // the blocks
+ QAtomicPointer<ElementType> _v[ConstantsType::BlockCount];
+ // the next free id
+ QAtomicInt _next;
+
+ // QFreeList is not copyable
+ Q_DISABLE_COPY(QFreeList)
+
+public:
+ inline QFreeList();
+ inline ~QFreeList();
+
+ // returns the payload for the given index \a x
+ inline ConstReferenceType at(int x) const;
+ inline ReferenceType operator[](int x);
+
+ /*
+ Return the next free id. Use this id to access the payload (see above).
+ Call release(id) when done using the id.
+ */
+ inline int next();
+ inline void release(int id);
+};
+
+template <typename T, typename ConstantsType>
+inline QFreeList<T, ConstantsType>::QFreeList()
+ : _next(ConstantsType::InitialNextValue)
+{ }
+
+template <typename T, typename ConstantsType>
+inline QFreeList<T, ConstantsType>::~QFreeList()
+{
+ for (int i = 0; i < ConstantsType::BlockCount; ++i)
+ delete [] static_cast<ElementType *>(_v[i]);
+}
+
+template <typename T, typename ConstantsType>
+inline typename QFreeList<T, ConstantsType>::ConstReferenceType QFreeList<T, ConstantsType>::at(int x) const
+{
+ const int block = blockfor(x);
+ return _v[block][x].t();
+}
+
+template <typename T, typename ConstantsType>
+inline typename QFreeList<T, ConstantsType>::ReferenceType QFreeList<T, ConstantsType>::operator[](int x)
+{
+ const int block = blockfor(x);
+ return _v[block][x].t();
+}
+
+template <typename T, typename ConstantsType>
+inline int QFreeList<T, ConstantsType>::next()
+{
+ int id, newid, at;
+ ElementType *v;
+ do {
+ id = _next; // .loadAqcuire();
+
+ at = id & ConstantsType::IndexMask;
+ const int block = blockfor(at);
+ v = _v[block];
+
+ if (!v) {
+ v = allocate((id & ConstantsType::IndexMask) - at, ConstantsType::Sizes[block]);
+ if (!_v[block].testAndSetRelease(0, v)) {
+ // race with another thread lost
+ delete [] v;
+ v = _v[block];
+ Q_ASSERT(v != 0);
+ }
+ }
+
+ newid = v[at].next | (id & ~ConstantsType::IndexMask);
+ } while (!_next.testAndSetRelease(id, newid));
+ // qDebug("QFreeList::next(): returning %d (_next now %d, serial %d)",
+ // id & ConstantsType::IndexMask,
+ // newid & ConstantsType::IndexMask,
+ // (newid & ~ConstantsType::IndexMask) >> 24);
+ return id & ConstantsType::IndexMask;
+}
+
+template <typename T, typename ConstantsType>
+inline void QFreeList<T, ConstantsType>::release(int id)
+{
+ int at = id & ConstantsType::IndexMask;
+ const int block = blockfor(at);
+ ElementType *v = _v[block];
+
+ int x, newid;
+ do {
+ x = _next; // .loadAcquire();
+ v[at].next = x & ConstantsType::IndexMask;
+
+ newid = incrementserial(x, id);
+ } while (!_next.testAndSetRelease(x, newid));
+ // qDebug("QFreeList::release(%d): _next now %d (was %d), serial %d",
+ // id & ConstantsType::IndexMask,
+ // newid & ConstantsType::IndexMask,
+ // x & ConstantsType::IndexMask,
+ // (newid & ~ConstantsType::IndexMask) >> 24);
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QFREELIST_P_H
diff --git a/src/corelib/tools/qharfbuzz.cpp b/src/corelib/tools/qharfbuzz.cpp
index 68f780d9fd..324cd481ed 100644
--- a/src/corelib/tools/qharfbuzz.cpp
+++ b/src/corelib/tools/qharfbuzz.cpp
@@ -102,7 +102,7 @@ HB_UChar16 HB_GetMirroredChar(HB_UChar16 ch)
return QChar::mirroredChar(ch);
}
-void *HB_Library_Resolve(const char *library, int version, const char *symbol)
+void (*HB_Library_Resolve(const char *library, int version, const char *symbol))()
{
#ifdef QT_NO_LIBRARY
return 0;
diff --git a/src/corelib/tools/qshareddata.h b/src/corelib/tools/qshareddata.h
index 9b404bdf0c..811b186e8b 100644
--- a/src/corelib/tools/qshareddata.h
+++ b/src/corelib/tools/qshareddata.h
@@ -279,6 +279,9 @@ namespace std {
QT_BEGIN_NAMESPACE
#endif
+template<typename T> Q_DECLARE_TYPEINFO_BODY(QSharedDataPointer<T>, Q_MOVABLE_TYPE);
+template<typename T> Q_DECLARE_TYPEINFO_BODY(QExplicitlySharedDataPointer<T>, Q_MOVABLE_TYPE);
+
QT_END_NAMESPACE
QT_END_HEADER
diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp
index 9e238193a3..9ce5eead8c 100644
--- a/src/corelib/tools/qstring.cpp
+++ b/src/corelib/tools/qstring.cpp
@@ -1267,10 +1267,10 @@ void QString::resize(int size)
QString::free(d);
d = x;
} else {
- if (d->ref != 1 || size > d->alloc ||
- (!d->capacityReserved && size < d->size && size < d->alloc >> 1))
+ if (d->ref != 1 || size > int(d->alloc) ||
+ (!d->capacityReserved && size < d->size && size < int(d->alloc) >> 1))
realloc(grow(size));
- if (d->alloc >= size) {
+ if (int(d->alloc) >= size) {
d->size = size;
d->data()[size] = '\0';
}
@@ -1560,7 +1560,7 @@ QString &QString::append(const QString &str)
if (d == &shared_null.str) {
operator=(str);
} else {
- if (d->ref != 1 || d->size + str.d->size > d->alloc)
+ if (d->ref != 1 || d->size + str.d->size > int(d->alloc))
realloc(grow(d->size + str.d->size));
memcpy(d->data() + d->size, str.d->data(), str.d->size * sizeof(QChar));
d->size += str.d->size;
@@ -1580,7 +1580,7 @@ QString &QString::append(const QLatin1String &str)
const uchar *s = (const uchar *)str.latin1();
if (s) {
int len = qstrlen((char *)s);
- if (d->ref != 1 || d->size + len > d->alloc)
+ if (d->ref != 1 || d->size + len > int(d->alloc))
realloc(grow(d->size + len));
ushort *i = d->data() + d->size;
while ((*i++ = *s++))
@@ -1623,7 +1623,7 @@ QString &QString::append(const QLatin1String &str)
*/
QString &QString::append(QChar ch)
{
- if (d->ref != 1 || d->size + 1 > d->alloc)
+ if (d->ref != 1 || d->size + 1 > int(d->alloc))
realloc(grow(d->size + 1));
d->data()[d->size++] = ch.unicode();
d->data()[d->size] = '\0';
@@ -3550,8 +3550,8 @@ static QByteArray toLatin1_helper(const QChar *data, int length)
const __m128i questionMark = _mm_set1_epi16('?');
// SSE has no compare instruction for unsigned comparison.
// The variables must be shiffted + 0x8000 to be compared
- const __m128i signedBitOffset = _mm_set1_epi16(0x8000);
- const __m128i thresholdMask = _mm_set1_epi16(0xff + 0x8000);
+ const __m128i signedBitOffset = _mm_set1_epi16(short(0x8000));
+ const __m128i thresholdMask = _mm_set1_epi16(short(0xff + 0x8000));
for (int i = 0; i < chunkCount; ++i) {
__m128i chunk1 = _mm_loadu_si128((__m128i*)src); // load
src += 8;
@@ -6152,7 +6152,7 @@ QString QString::repeated(int times) const
QString result;
result.reserve(resultSize);
- if (result.d->alloc != resultSize)
+ if (int(result.d->alloc) != resultSize)
return QString(); // not enough memory
memcpy(result.d->data(), d->data(), d->size * sizeof(ushort));
diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h
index af3e3f3ff9..209994de16 100644
--- a/src/corelib/tools/qstring.h
+++ b/src/corelib/tools/qstring.h
@@ -97,36 +97,43 @@ template<int N> struct QConstStringDataPtr
};
#if defined(Q_COMPILER_UNICODE_STRINGS)
-template<int n> struct QConstStringData
+template<int N> struct QConstStringData
{
const QStringData str;
- const char16_t data[n];
+ const char16_t data[N + 1];
};
-#define QT_QSTRING_UNICODE_MARKER u""
+
+#define QT_UNICODE_LITERAL_II(str) u"" str
#elif defined(Q_OS_WIN) || (defined(__SIZEOF_WCHAR_T__) && __SIZEOF_WCHAR_T__ == 2) || defined(WCHAR_MAX) && (WCHAR_MAX - 0 < 65536)
// wchar_t is 2 bytes
-template<int n> struct QConstStringData
+template<int N> struct QConstStringData
{
const QStringData str;
- const wchar_t data[n];
+ const wchar_t data[N + 1];
};
-#define QT_QSTRING_UNICODE_MARKER L""
+
+#if defined(Q_CC_MSVC)
+# define QT_UNICODE_LITERAL_II(str) L##str
+#else
+# define QT_UNICODE_LITERAL_II(str) L"" str
+#endif
#else
-template<int n> struct QConstStringData
+template<int N> struct QConstStringData
{
const QStringData str;
- const ushort data[n];
+ const ushort data[N + 1];
};
#endif
-#if defined(QT_QSTRING_UNICODE_MARKER)
+#if defined(QT_UNICODE_LITERAL_II)
+# define QT_UNICODE_LITERAL(str) QT_UNICODE_LITERAL_II(str)
# if defined(Q_COMPILER_LAMBDA)
-# define QStringLiteral(str) ([]() { \
- enum { Size = sizeof(QT_QSTRING_UNICODE_MARKER str)/2 }; \
+# define QStringLiteral(str) ([]() -> QConstStringDataPtr<sizeof(QT_UNICODE_LITERAL(str))/2 - 1> { \
+ enum { Size = sizeof(QT_UNICODE_LITERAL(str))/2 - 1 }; \
static const QConstStringData<Size> qstring_literal = \
- { { Q_REFCOUNT_INITIALIZER(-1), Size -1, 0, 0, { 0 } }, QT_QSTRING_UNICODE_MARKER str }; \
+ { { Q_REFCOUNT_INITIALIZER(-1), Size, 0, 0, { 0 } }, QT_UNICODE_LITERAL(str) }; \
QConstStringDataPtr<Size> holder = { &qstring_literal }; \
return holder; }())
@@ -137,9 +144,9 @@ template<int n> struct QConstStringData
# define QStringLiteral(str) \
__extension__ ({ \
- enum { Size = sizeof(QT_QSTRING_UNICODE_MARKER str)/2 }; \
+ enum { Size = sizeof(QT_UNICODE_LITERAL(str))/2 - 1 }; \
static const QConstStringData<Size> qstring_literal = \
- { { Q_REFCOUNT_INITIALIZER(-1), Size -1, 0, 0, { 0 } }, QT_QSTRING_UNICODE_MARKER str }; \
+ { { Q_REFCOUNT_INITIALIZER(-1), Size, 0, 0, { 0 } }, QT_UNICODE_LITERAL(str) }; \
QConstStringDataPtr<Size> holder = { &qstring_literal }; \
holder; })
# endif
diff --git a/src/corelib/tools/qstringbuilder.cpp b/src/corelib/tools/qstringbuilder.cpp
index 4c6848498b..7c1bde4ac7 100644
--- a/src/corelib/tools/qstringbuilder.cpp
+++ b/src/corelib/tools/qstringbuilder.cpp
@@ -108,13 +108,12 @@ QT_BEGIN_NAMESPACE
*/
/*! \internal
- Note: The len contains the ending \0
*/
void QAbstractConcatenable::convertFromAscii(const char *a, int len, QChar *&out)
{
#ifndef QT_NO_TEXTCODEC
if (QString::codecForCStrings && len) {
- QString tmp = QString::fromAscii(a, len > 0 ? len - 1 : -1);
+ QString tmp = QString::fromAscii(a, len > 0 ? len : -1);
memcpy(out, reinterpret_cast<const char *>(tmp.constData()), sizeof(QChar) * tmp.size());
out += tmp.length();
return;
@@ -126,7 +125,7 @@ void QAbstractConcatenable::convertFromAscii(const char *a, int len, QChar *&out
while (*a)
*out++ = QLatin1Char(*a++);
} else {
- for (int i = 0; i < len - 1; ++i)
+ for (int i = 0; i < len; ++i)
*out++ = QLatin1Char(a[i]);
}
}
diff --git a/src/corelib/tools/qstringbuilder.h b/src/corelib/tools/qstringbuilder.h
index 6d998b62aa..30b81c42f4 100644
--- a/src/corelib/tools/qstringbuilder.h
+++ b/src/corelib/tools/qstringbuilder.h
@@ -294,7 +294,7 @@ template <int N> struct QConcatenable<char[N]> : private QAbstractConcatenable
#ifndef QT_NO_CAST_FROM_ASCII
static inline void QT_ASCII_CAST_WARN appendTo(const char a[N], QChar *&out)
{
- QAbstractConcatenable::convertFromAscii(a, N, out);
+ QAbstractConcatenable::convertFromAscii(a, N - 1, out);
}
#endif
static inline void appendTo(const char a[N], char *&out)
@@ -313,7 +313,7 @@ template <int N> struct QConcatenable<const char[N]> : private QAbstractConcaten
#ifndef QT_NO_CAST_FROM_ASCII
static inline void QT_ASCII_CAST_WARN appendTo(const char a[N], QChar *&out)
{
- QAbstractConcatenable::convertFromAscii(a, N, out);
+ QAbstractConcatenable::convertFromAscii(a, N - 1, out);
}
#endif
static inline void appendTo(const char a[N], char *&out)
@@ -349,10 +349,9 @@ template <> struct QConcatenable<QByteArray> : private QAbstractConcatenable
enum { ExactSize = false };
static int size(const QByteArray &ba) { return ba.size(); }
#ifndef QT_NO_CAST_FROM_ASCII
- static inline void appendTo(const QByteArray &ba, QChar *&out)
+ static inline QT_ASCII_CAST_WARN void appendTo(const QByteArray &ba, QChar *&out)
{
- // adding 1 because convertFromAscii expects the size including the null-termination
- QAbstractConcatenable::convertFromAscii(ba.constData(), ba.size() + 1, out);
+ QAbstractConcatenable::convertFromAscii(ba.constData(), ba.size(), out);
}
#endif
static inline void appendTo(const QByteArray &ba, char *&out)
@@ -364,6 +363,26 @@ template <> struct QConcatenable<QByteArray> : private QAbstractConcatenable
}
};
+template <int N> struct QConcatenable<QConstByteArrayDataPtr<N> > : private QAbstractConcatenable
+{
+ typedef QConstByteArrayDataPtr<N> type;
+ typedef QByteArray ConvertTo;
+ enum { ExactSize = false };
+ static int size(const type &) { return N; }
+#ifndef QT_NO_CAST_FROM_ASCII
+ static inline QT_ASCII_CAST_WARN void appendTo(const type &a, QChar *&out)
+ {
+ QAbstractConcatenable::convertFromAscii(a.ptr->data, N, out);
+ }
+#endif
+ static inline void appendTo(const type &ba, char *&out)
+ {
+ const char *a = ba.ptr->data;
+ while (*a)
+ *out++ = *a++;
+ }
+};
+
namespace QtStringBuilder {
template <typename A, typename B> struct ConvertToTypeHelper
{ typedef A ConvertTo; };
diff --git a/src/corelib/tools/tools.pri b/src/corelib/tools/tools.pri
index f5b38eb1c0..13b597d513 100644
--- a/src/corelib/tools/tools.pri
+++ b/src/corelib/tools/tools.pri
@@ -13,6 +13,7 @@ HEADERS += \
tools/qdatetime.h \
tools/qdatetime_p.h \
tools/qeasingcurve.h \
+ tools/qfreelist_p.h \
tools/qhash.h \
tools/qline.h \
tools/qlinkedlist.h \
@@ -61,6 +62,7 @@ SOURCES += \
tools/qdatetime.cpp \
tools/qeasingcurve.cpp \
tools/qelapsedtimer.cpp \
+ tools/qfreelist.cpp \
tools/qhash.cpp \
tools/qline.cpp \
tools/qlinkedlist.cpp \
diff --git a/src/dbus/qdbus_symbols.cpp b/src/dbus/qdbus_symbols.cpp
index fed18350bb..8e74b8b922 100644
--- a/src/dbus/qdbus_symbols.cpp
+++ b/src/dbus/qdbus_symbols.cpp
@@ -48,7 +48,7 @@
QT_BEGIN_NAMESPACE
-void *qdbus_resolve_me(const char *name);
+void (*qdbus_resolve_me(const char *name))();
#if !defined QT_LINKED_LIBDBUS
@@ -95,20 +95,19 @@ bool qdbus_loadLibDBus()
return false;
}
-void *qdbus_resolve_conditionally(const char *name)
+void (*qdbus_resolve_conditionally(const char *name))()
{
if (qdbus_loadLibDBus())
return qdbus_libdbus->resolve(name);
return 0;
}
-void *qdbus_resolve_me(const char *name)
+void (*qdbus_resolve_me(const char *name))()
{
- void *ptr = 0;
if (!qdbus_loadLibDBus())
qFatal("Cannot find libdbus-1 in your system to resolve symbol '%s'.", name);
- ptr = qdbus_libdbus->resolve(name);
+ QFunctionPointer ptr = qdbus_libdbus->resolve(name);
if (!ptr)
qFatal("Cannot resolve '%s' in your libdbus-1.", name);
diff --git a/src/dbus/qdbus_symbols_p.h b/src/dbus/qdbus_symbols_p.h
index a59c08a8ab..8178e2ecf3 100644
--- a/src/dbus/qdbus_symbols_p.h
+++ b/src/dbus/qdbus_symbols_p.h
@@ -63,8 +63,8 @@ QT_BEGIN_NAMESPACE
#if !defined QT_LINKED_LIBDBUS
-void *qdbus_resolve_conditionally(const char *name); // doesn't print a warning
-void *qdbus_resolve_me(const char *name); // prints a warning
+void (*qdbus_resolve_conditionally(const char *name))(); // doesn't print a warning
+void (*qdbus_resolve_me(const char *name))(); // prints a warning
bool qdbus_loadLibDBus();
# define DEFINEFUNC(ret, func, args, argcall, funcret) \
diff --git a/src/dbus/qdbusmetaobject.cpp b/src/dbus/qdbusmetaobject.cpp
index d12642d632..8daf2300b7 100644
--- a/src/dbus/qdbusmetaobject.cpp
+++ b/src/dbus/qdbusmetaobject.cpp
@@ -125,6 +125,11 @@ private:
MethodScriptable = 0x40
};
+ enum MetaObjectFlags {
+ DynamicMetaObject = 0x01,
+ RequiresVariantMetaObject = 0x02
+ };
+
QMap<QByteArray, Method> methods;
QMap<QByteArray, Property> properties;
@@ -152,6 +157,8 @@ struct QDBusMetaObjectPrivate
int methodCount, methodData;
int propertyCount, propertyData;
int enumeratorCount, enumeratorData;
+ int constructorCount, constructorData; // since revision 2
+ int flags; // since revision 3
// this is specific for QDBusMetaObject:
int propertyDBusData;
@@ -416,7 +423,7 @@ void QDBusMetaObjectGenerator::write(QDBusMetaObject *obj)
idata.resize(sizeof(QDBusMetaObjectPrivate) / sizeof(int));
QDBusMetaObjectPrivate *header = reinterpret_cast<QDBusMetaObjectPrivate *>(idata.data());
- header->revision = 1;
+ header->revision = 3;
header->className = 0;
header->classInfoCount = 0;
header->classInfoData = 0;
@@ -426,6 +433,9 @@ void QDBusMetaObjectGenerator::write(QDBusMetaObject *obj)
header->propertyData = header->methodData + header->methodCount * 5;
header->enumeratorCount = 0;
header->enumeratorData = 0;
+ header->constructorCount = 0;
+ header->constructorData = 0;
+ header->flags = RequiresVariantMetaObject;
header->propertyDBusData = header->propertyData + header->propertyCount * 3;
header->methodDBusData = header->propertyDBusData + header->propertyCount * intsPerProperty;
diff --git a/src/gui/image/qbmphandler.cpp b/src/gui/image/qbmphandler.cpp
index 7848bc96f3..d854b1765b 100644
--- a/src/gui/image/qbmphandler.cpp
+++ b/src/gui/image/qbmphandler.cpp
@@ -97,8 +97,10 @@ static QDataStream &operator<<(QDataStream &s, const BMP_FILEHDR &bf)
const int BMP_OLD = 12; // old Windows/OS2 BMP size
-const int BMP_WIN = 40; // new Windows BMP size
+const int BMP_WIN = 40; // Windows BMP v3 size
const int BMP_OS2 = 64; // new OS/2 BMP size
+const int BMP_WIN4 = 108; // Windows BMP v4 size
+const int BMP_WIN5 = 124; // Windows BMP v5 size
const int BMP_RGB = 0; // no compression
const int BMP_RLE8 = 1; // run-length encoded, 8 bits
@@ -109,7 +111,7 @@ const int BMP_BITFIELDS = 3; // RGB values encoded in dat
static QDataStream &operator>>(QDataStream &s, BMP_INFOHDR &bi)
{
s >> bi.biSize;
- if (bi.biSize == BMP_WIN || bi.biSize == BMP_OS2) {
+ if (bi.biSize == BMP_WIN || bi.biSize == BMP_OS2 || bi.biSize == BMP_WIN4 || bi.biSize == BMP_WIN5) {
s >> bi.biWidth >> bi.biHeight >> bi.biPlanes >> bi.biBitCount;
s >> bi.biCompression >> bi.biSizeImage;
s >> bi.biXPelsPerMeter >> bi.biYPelsPerMeter;
@@ -255,7 +257,57 @@ static bool read_dib_body(QDataStream &s, const BMP_INFOHDR &bi, int offset, int
image.setDotsPerMeterY(bi.biYPelsPerMeter);
if (!d->isSequential())
- d->seek(startpos + BMP_FILEHDR_SIZE + bi.biSize); // goto start of colormap
+ d->seek(startpos + BMP_FILEHDR_SIZE + (bi.biSize >= BMP_WIN4? BMP_WIN : bi.biSize)); // goto start of colormap
+
+ if (bi.biSize >= BMP_WIN4 || (comp == BMP_BITFIELDS && (nbits == 16 || nbits == 32))) {
+ Q_ASSERT(ncols == 0);
+
+ if (d->read((char *)&red_mask, sizeof(red_mask)) != sizeof(red_mask))
+ return false;
+ if (d->read((char *)&green_mask, sizeof(green_mask)) != sizeof(green_mask))
+ return false;
+ if (d->read((char *)&blue_mask, sizeof(blue_mask)) != sizeof(blue_mask))
+ return false;
+
+ // Read BMP v4+ header
+ if (bi.biSize >= BMP_WIN4) {
+ int alpha_mask = 0;
+ int CSType = 0;
+ int gamma_red = 0;
+ int gamma_green = 0;
+ int gamma_blue = 0;
+ int endpoints[9];
+
+ if (d->read((char *)&alpha_mask, sizeof(alpha_mask)) != sizeof(alpha_mask))
+ return false;
+ if (d->read((char *)&CSType, sizeof(CSType)) != sizeof(CSType))
+ return false;
+ if (d->read((char *)&endpoints, sizeof(endpoints)) != sizeof(endpoints))
+ return false;
+ if (d->read((char *)&gamma_red, sizeof(gamma_red)) != sizeof(gamma_red))
+ return false;
+ if (d->read((char *)&gamma_green, sizeof(gamma_green)) != sizeof(gamma_green))
+ return false;
+ if (d->read((char *)&gamma_blue, sizeof(gamma_blue)) != sizeof(gamma_blue))
+ return false;
+
+ if (bi.biSize == BMP_WIN5) {
+ qint32 intent = 0;
+ qint32 profileData = 0;
+ qint32 profileSize = 0;
+ qint32 reserved = 0;
+
+ if (d->read((char *)&intent, sizeof(intent)) != sizeof(intent))
+ return false;
+ if (d->read((char *)&profileData, sizeof(profileData)) != sizeof(profileData))
+ return false;
+ if (d->read((char *)&profileSize, sizeof(profileSize)) != sizeof(profileSize))
+ return false;
+ if (d->read((char *)&reserved, sizeof(reserved)) != sizeof(reserved) || reserved != 0)
+ return false;
+ }
+ }
+ }
if (ncols > 0) { // read color table
uchar rgb[4];
@@ -268,12 +320,6 @@ static bool read_dib_body(QDataStream &s, const BMP_INFOHDR &bi, int offset, int
return false;
}
} else if (comp == BMP_BITFIELDS && (nbits == 16 || nbits == 32)) {
- if (d->read((char *)&red_mask, sizeof(red_mask)) != sizeof(red_mask))
- return false;
- if (d->read((char *)&green_mask, sizeof(green_mask)) != sizeof(green_mask))
- return false;
- if (d->read((char *)&blue_mask, sizeof(blue_mask)) != sizeof(blue_mask))
- return false;
red_shift = calc_shift(red_mask);
red_scale = 256 / ((red_mask >> red_shift) + 1);
green_shift = calc_shift(green_mask);
diff --git a/src/gui/image/qtiffhandler.cpp b/src/gui/image/qtiffhandler.cpp
index c753b83294..4dc9775d46 100644
--- a/src/gui/image/qtiffhandler.cpp
+++ b/src/gui/image/qtiffhandler.cpp
@@ -236,14 +236,14 @@ bool QTiffHandler::read(QImage *image)
}
} else {
// create the color table
- uint16 *redTable = static_cast<uint16 *>(qMalloc(tableSize * sizeof(uint16)));
- uint16 *greenTable = static_cast<uint16 *>(qMalloc(tableSize * sizeof(uint16)));
- uint16 *blueTable = static_cast<uint16 *>(qMalloc(tableSize * sizeof(uint16)));
- if (!redTable || !greenTable || !blueTable) {
+ uint16 *redTable = 0;
+ uint16 *greenTable = 0;
+ uint16 *blueTable = 0;
+ if (!TIFFGetField(tiff, TIFFTAG_COLORMAP, &redTable, &greenTable, &blueTable)) {
TIFFClose(tiff);
return false;
}
- if (!TIFFGetField(tiff, TIFFTAG_COLORMAP, &redTable, &greenTable, &blueTable)) {
+ if (!redTable || !greenTable || !blueTable) {
TIFFClose(tiff);
return false;
}
@@ -500,6 +500,9 @@ bool QTiffHandler::write(const QImage &image)
uint16 *greenTable = static_cast<uint16 *>(qMalloc(256 * sizeof(uint16)));
uint16 *blueTable = static_cast<uint16 *>(qMalloc(256 * sizeof(uint16)));
if (!redTable || !greenTable || !blueTable) {
+ qFree(redTable);
+ qFree(greenTable);
+ qFree(blueTable);
TIFFClose(tiff);
return false;
}
diff --git a/src/gui/math3d/qmatrix4x4.cpp b/src/gui/math3d/qmatrix4x4.cpp
index 837bd519b8..cef92af66b 100644
--- a/src/gui/math3d/qmatrix4x4.cpp
+++ b/src/gui/math3d/qmatrix4x4.cpp
@@ -55,6 +55,20 @@ QT_BEGIN_NAMESPACE
\since 4.6
\ingroup painting-3D
+ The QMatrix4x4 class in general is treated as a row-major matrix, in that the
+ constructors and operator() functions take data in row-major format, as is
+ familiar in C-style usage.
+
+ Internally the data is stored as column-major format, so as to be optimal for
+ passing to OpenGL functions, which expect column-major data.
+
+ When using these functions be aware that they return data in \bold{column-major}
+ format:
+ \list
+ \o data()
+ \o constData()
+ \endlist
+
\sa QVector3D, QGenericMatrix
*/
@@ -1725,6 +1739,7 @@ QRectF QMatrix4x4::mapRect(const QRectF& rect) const
\fn const qreal *QMatrix4x4::data() const
Returns a constant pointer to the raw data of this matrix.
+ This raw data is stored in column-major format.
\sa constData()
*/
@@ -1733,6 +1748,7 @@ QRectF QMatrix4x4::mapRect(const QRectF& rect) const
\fn const qreal *QMatrix4x4::constData() const
Returns a constant pointer to the raw data of this matrix.
+ This raw data is stored in column-major format.
\sa data()
*/
diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp
index 908fdf1183..566b4d5f61 100644
--- a/src/gui/painting/qpaintengine_raster.cpp
+++ b/src/gui/painting/qpaintengine_raster.cpp
@@ -3005,7 +3005,7 @@ void QRasterPaintEngine::drawStaticTextItem(QStaticTextItem *textItem)
ensureState();
QFontEngine *fontEngine = textItem->fontEngine();
- if (!supportsTransformations(fontEngine)) {
+ if (shouldDrawCachedGlyphs(fontEngine->fontDef.pixelSize, state()->matrix)) {
drawCachedGlyphs(textItem->numGlyphs, textItem->glyphs, textItem->glyphPositions,
fontEngine);
} else {
@@ -3355,10 +3355,7 @@ bool QRasterPaintEngine::supportsTransformations(qreal pixelSize, const QTransfo
#endif
return true;
- if (pixelSize * pixelSize * qAbs(m.determinant()) >= 64 * 64)
- return true;
-
- return false;
+ return !shouldDrawCachedGlyphs(pixelSize, m);
}
/*!
diff --git a/src/gui/painting/qpaintengineex.cpp b/src/gui/painting/qpaintengineex.cpp
index 9427dd5105..5ef6900cc8 100644
--- a/src/gui/painting/qpaintengineex.cpp
+++ b/src/gui/painting/qpaintengineex.cpp
@@ -53,6 +53,10 @@
QT_BEGIN_NAMESPACE
+#if !defined(QT_MAX_CACHED_GLYPH_SIZE)
+# define QT_MAX_CACHED_GLYPH_SIZE 64
+#endif
+
/*******************************************************************************
*
* class QVectorPath
@@ -1096,4 +1100,10 @@ bool QPaintEngineEx::supportsTransformations(qreal pixelSize, const QTransform &
return false;
}
+bool QPaintEngineEx::shouldDrawCachedGlyphs(qreal pixelSize, const QTransform &m) const
+{
+ return (pixelSize * pixelSize * qAbs(m.determinant())) <
+ QT_MAX_CACHED_GLYPH_SIZE * QT_MAX_CACHED_GLYPH_SIZE;
+}
+
QT_END_NAMESPACE
diff --git a/src/gui/painting/qpaintengineex_p.h b/src/gui/painting/qpaintengineex_p.h
index 604a43133f..d9ab506c94 100644
--- a/src/gui/painting/qpaintengineex_p.h
+++ b/src/gui/painting/qpaintengineex_p.h
@@ -228,6 +228,7 @@ public:
};
virtual uint flags() const {return 0;}
virtual bool supportsTransformations(qreal pixelSize, const QTransform &m) const;
+ virtual bool shouldDrawCachedGlyphs(qreal pixelSize, const QTransform &m) const;
protected:
QPaintEngineEx(QPaintEngineExPrivate &data);
diff --git a/src/gui/text/qfontengine_p.h b/src/gui/text/qfontengine_p.h
index 6ae410cada..c53e841cf4 100644
--- a/src/gui/text/qfontengine_p.h
+++ b/src/gui/text/qfontengine_p.h
@@ -155,6 +155,7 @@ public:
struct FaceId {
FaceId() : index(0), encoding(0) {}
QByteArray filename;
+ QByteArray uuid;
int index;
int encoding;
};
@@ -303,7 +304,7 @@ inline bool operator ==(const QFontEngine::FaceId &f1, const QFontEngine::FaceId
inline uint qHash(const QFontEngine::FaceId &f)
{
- return qHash((f.index << 16) + f.encoding) + qHash(f.filename);
+ return qHash((f.index << 16) + f.encoding) + qHash(f.filename + f.uuid);
}
diff --git a/src/gui/text/qrawfont.cpp b/src/gui/text/qrawfont.cpp
index 4c65ad5de0..26b6a8aad7 100644
--- a/src/gui/text/qrawfont.cpp
+++ b/src/gui/text/qrawfont.cpp
@@ -139,7 +139,7 @@ QRawFont::QRawFont()
\note The referenced file must contain a TrueType or OpenType font.
*/
QRawFont::QRawFont(const QString &fileName,
- int pixelSize,
+ qreal pixelSize,
QFont::HintingPreference hintingPreference)
: d(new QRawFontPrivate)
{
@@ -154,7 +154,7 @@ QRawFont::QRawFont(const QString &fileName,
\note The data must contain a TrueType or OpenType font.
*/
QRawFont::QRawFont(const QByteArray &fontData,
- int pixelSize,
+ qreal pixelSize,
QFont::HintingPreference hintingPreference)
: d(new QRawFontPrivate)
{
@@ -204,7 +204,7 @@ bool QRawFont::isValid() const
\sa loadFromData()
*/
void QRawFont::loadFromFile(const QString &fileName,
- int pixelSize,
+ qreal pixelSize,
QFont::HintingPreference hintingPreference)
{
QFile file(fileName);
@@ -222,7 +222,7 @@ void QRawFont::loadFromFile(const QString &fileName,
\sa loadFromFile()
*/
void QRawFont::loadFromData(const QByteArray &fontData,
- int pixelSize,
+ qreal pixelSize,
QFont::HintingPreference hintingPreference)
{
detach();
diff --git a/src/gui/text/qrawfont.h b/src/gui/text/qrawfont.h
index e94bd99b8c..f7d7494f0b 100644
--- a/src/gui/text/qrawfont.h
+++ b/src/gui/text/qrawfont.h
@@ -70,10 +70,10 @@ public:
QRawFont();
QRawFont(const QString &fileName,
- int pixelSize,
+ qreal pixelSize,
QFont::HintingPreference hintingPreference = QFont::PreferDefaultHinting);
QRawFont(const QByteArray &fontData,
- int pixelSize,
+ qreal pixelSize,
QFont::HintingPreference hintingPreference = QFont::PreferDefaultHinting);
QRawFont(const QRawFont &other);
~QRawFont();
@@ -117,11 +117,11 @@ public:
qreal unitsPerEm() const;
void loadFromFile(const QString &fileName,
- int pixelSize,
+ qreal pixelSize,
QFont::HintingPreference hintingPreference);
void loadFromData(const QByteArray &fontData,
- int pixelSize,
+ qreal pixelSize,
QFont::HintingPreference hintingPreference);
bool supportsCharacter(quint32 ucs4) const;
diff --git a/src/gui/text/qrawfont_ft.cpp b/src/gui/text/qrawfont_ft.cpp
index db60459176..1666df3fdf 100644
--- a/src/gui/text/qrawfont_ft.cpp
+++ b/src/gui/text/qrawfont_ft.cpp
@@ -45,6 +45,7 @@
#include "qrawfont_p.h"
#include "qfontengine_ft_p.h"
+#include "quuid.h"
#if defined(Q_WS_X11) && !defined(QT_NO_FONTCONFIG)
# include "qfontengine_x11_p.h"
@@ -87,6 +88,7 @@ public:
FaceId faceId;
faceId.filename = "";
faceId.index = 0;
+ faceId.uuid = QUuid::createUuid().toByteArray();
return init(faceId, true, Format_None, fontData);
}
@@ -98,7 +100,7 @@ void QRawFontPrivate::platformCleanUp()
// Font engine handles all resources
}
-void QRawFontPrivate::platformLoadFromData(const QByteArray &fontData, int pixelSize,
+void QRawFontPrivate::platformLoadFromData(const QByteArray &fontData, qreal pixelSize,
QFont::HintingPreference hintingPreference)
{
Q_ASSERT(fontEngine == 0);
diff --git a/src/gui/text/qrawfont_p.h b/src/gui/text/qrawfont_p.h
index 56ea6a031d..4a4ed56223 100644
--- a/src/gui/text/qrawfont_p.h
+++ b/src/gui/text/qrawfont_p.h
@@ -99,7 +99,7 @@ public:
void cleanUp();
void platformCleanUp();
void platformLoadFromData(const QByteArray &fontData,
- int pixelSize,
+ qreal pixelSize,
QFont::HintingPreference hintingPreference);
static QRawFontPrivate *get(const QRawFont &font) { return font.d.data(); }
diff --git a/src/gui/text/qrawfont_qpa.cpp b/src/gui/text/qrawfont_qpa.cpp
index b80b64cbaf..47815baf06 100644
--- a/src/gui/text/qrawfont_qpa.cpp
+++ b/src/gui/text/qrawfont_qpa.cpp
@@ -53,7 +53,7 @@ void QRawFontPrivate::platformCleanUp()
{
}
-void QRawFontPrivate::platformLoadFromData(const QByteArray &fontData, int pixelSize,
+void QRawFontPrivate::platformLoadFromData(const QByteArray &fontData, qreal pixelSize,
QFont::HintingPreference hintingPreference)
{
Q_ASSERT(fontEngine == 0);
diff --git a/src/gui/text/qtextcontrol.cpp b/src/gui/text/qtextcontrol.cpp
index 3d7e597f23..689fd4379b 100644
--- a/src/gui/text/qtextcontrol.cpp
+++ b/src/gui/text/qtextcontrol.cpp
@@ -1817,6 +1817,7 @@ void QTextControlPrivate::inputMethodEvent(QInputMethodEvent *e)
bool isGettingInput = !e->commitString().isEmpty()
|| e->preeditString() != cursor.block().layout()->preeditAreaText()
|| e->replacementLength() > 0;
+ bool forceSelectionChanged = false;
cursor.beginEditBlock();
if (isGettingInput) {
@@ -1840,6 +1841,7 @@ void QTextControlPrivate::inputMethodEvent(QInputMethodEvent *e)
cursor.setPosition(blockStart + a.length, QTextCursor::KeepAnchor);
q->ensureCursorVisible();
repaintOldAndNewSelection(oldCursor);
+ forceSelectionChanged = true;
}
}
@@ -1874,6 +1876,7 @@ void QTextControlPrivate::inputMethodEvent(QInputMethodEvent *e)
cursor_d->setX();
if (oldPreeditCursor != preeditCursor)
emit q->microFocusChanged();
+ selectionChanged(forceSelectionChanged);
}
QVariant QTextControl::inputMethodQuery(Qt::InputMethodQuery property) const
diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp
index 5cc3d73fb9..0d3aa0b585 100644
--- a/src/gui/text/qtextengine.cpp
+++ b/src/gui/text/qtextengine.cpp
@@ -1632,7 +1632,7 @@ bool QTextEngine::isRightToLeft() const
int QTextEngine::findItem(int strPos) const
{
itemize();
- int left = 0;
+ int left = 1;
int right = layoutData->items.size()-1;
while(left <= right) {
int middle = ((right-left)/2)+left;
diff --git a/src/gui/util/qvalidator.cpp b/src/gui/util/qvalidator.cpp
index b32bea8b7a..43251a8829 100644
--- a/src/gui/util/qvalidator.cpp
+++ b/src/gui/util/qvalidator.cpp
@@ -131,6 +131,69 @@ QT_BEGIN_NAMESPACE
\omitvalue Valid
*/
+
+/*!
+ \fn void QIntValidator::topChanged(int top)
+
+ This signal is emitted after the top property changed.
+
+ \sa QIntValidator::top(), QIntValidator::setTop(), QIntValidator::bottom(), QIntValidator::setBottom()
+ \internal
+*/
+
+/*!
+ \fn void QIntValidator::bottomChanged(int bottom)
+
+ This signal is emitted after the bottom property changed.
+
+ \sa QIntValidator::top(), QIntValidator::setTop(), QIntValidator::bottom(), QIntValidator::setBottom()
+ \internal
+*/
+
+/*!
+ \fn void QDoubleValidator::topChanged(int top)
+
+ This signal is emitted after the top property changed.
+
+ \sa QDoubleValidator::top(), QDoubleValidator::setTop(), QDoubleValidator::bottom(), QDoubleValidator::setBottom()
+ \internal
+*/
+
+/*!
+ \fn void QDoubleValidator::bottomChanged(int bottom)
+
+ This signal is emitted after the bottom property changed.
+
+ \sa QDoubleValidator::top(), QDoubleValidator::setTop(), QDoubleValidator::bottom(), QDoubleValidator::setBottom()
+ \internal
+*/
+
+/*!
+ \fn void QDoubleValidator::decimalsChanged(int decimals)
+
+ This signal is emitted after the decimals property changed.
+
+ \internal
+*/
+
+/*!
+ \fn void QDoubleValidator::notationChanged(QDoubleValidator::Notation notation)
+
+ This signal is emitted after the notation property changed.
+
+ QDoubleValidator::Notation is not a registered metatype, so for queued connections,
+ you will have to register it with Q_DECLARE_METATYPE() and qRegisterMetaType().
+
+ \internal
+*/
+
+/*!
+ \fn void QRegExpValidator::regExpChanged(const QRegExp &regExp)
+
+ This signal is emitted after the regExp property changed.
+ \internal
+*/
+
class QValidatorPrivate : public QObjectPrivate{
Q_DECLARE_PUBLIC(QValidator)
public:
@@ -436,8 +499,15 @@ void QIntValidator::fixup(QString &input) const
void QIntValidator::setRange(int bottom, int top)
{
- b = bottom;
- t = top;
+ if (b != bottom) {
+ b = bottom;
+ emit bottomChanged(b);
+ }
+
+ if (t != top) {
+ t = top;
+ emit topChanged(t);
+ }
}
@@ -710,9 +780,20 @@ QValidator::State QDoubleValidatorPrivate::validateWithLocale(QString &input, QL
void QDoubleValidator::setRange(double minimum, double maximum, int decimals)
{
- b = minimum;
- t = maximum;
- dec = decimals;
+ if (b != minimum) {
+ b = minimum;
+ emit bottomChanged(b);
+ }
+
+ if (t != maximum) {
+ t = maximum;
+ emit topChanged(t);
+ }
+
+ if (dec != decimals) {
+ dec = decimals;
+ emit decimalsChanged(dec);
+ }
}
/*!
@@ -771,7 +852,10 @@ void QDoubleValidator::setDecimals(int decimals)
void QDoubleValidator::setNotation(Notation newNotation)
{
Q_D(QDoubleValidator);
- d->notation = newNotation;
+ if (d->notation != newNotation) {
+ d->notation = newNotation;
+ emit notationChanged(d->notation);
+ }
}
QDoubleValidator::Notation QDoubleValidator::notation() const
@@ -915,7 +999,10 @@ QValidator::State QRegExpValidator::validate(QString &input, int& pos) const
void QRegExpValidator::setRegExp(const QRegExp& rx)
{
- r = rx;
+ if (r != rx) {
+ r = rx;
+ emit regExpChanged(r);
+ }
}
#endif
diff --git a/src/gui/util/qvalidator.h b/src/gui/util/qvalidator.h
index 70f656e6a8..cb0436cc3e 100644
--- a/src/gui/util/qvalidator.h
+++ b/src/gui/util/qvalidator.h
@@ -96,8 +96,8 @@ private:
class Q_GUI_EXPORT QIntValidator : public QValidator
{
Q_OBJECT
- Q_PROPERTY(int bottom READ bottom WRITE setBottom)
- Q_PROPERTY(int top READ top WRITE setTop)
+ Q_PROPERTY(int bottom READ bottom WRITE setBottom NOTIFY bottomChanged)
+ Q_PROPERTY(int top READ top WRITE setTop NOTIFY topChanged)
public:
explicit QIntValidator(QObject * parent = 0);
@@ -113,7 +113,9 @@ public:
int bottom() const { return b; }
int top() const { return t; }
-
+Q_SIGNALS:
+ void bottomChanged(int bottom);
+ void topChanged(int top);
#ifdef QT3_SUPPORT
public:
QT3_SUPPORT_CONSTRUCTOR QIntValidator(QObject * parent, const char *name);
@@ -134,11 +136,11 @@ class QDoubleValidatorPrivate;
class Q_GUI_EXPORT QDoubleValidator : public QValidator
{
Q_OBJECT
- Q_PROPERTY(double bottom READ bottom WRITE setBottom)
- Q_PROPERTY(double top READ top WRITE setTop)
- Q_PROPERTY(int decimals READ decimals WRITE setDecimals)
+ Q_PROPERTY(double bottom READ bottom WRITE setBottom NOTIFY bottomChanged)
+ Q_PROPERTY(double top READ top WRITE setTop NOTIFY topChanged)
+ Q_PROPERTY(int decimals READ decimals WRITE setDecimals NOTIFY decimalsChanged)
Q_ENUMS(Notation)
- Q_PROPERTY(Notation notation READ notation WRITE setNotation)
+ Q_PROPERTY(Notation notation READ notation WRITE setNotation NOTIFY notationChanged)
public:
explicit QDoubleValidator(QObject * parent = 0);
@@ -149,7 +151,6 @@ public:
StandardNotation,
ScientificNotation
};
-
QValidator::State validate(QString &, int &) const;
virtual void setRange(double bottom, double top, int decimals = 0);
@@ -163,6 +164,12 @@ public:
int decimals() const { return dec; }
Notation notation() const;
+Q_SIGNALS:
+ void bottomChanged(double bottom);
+ void topChanged(double top);
+ void decimalsChanged(int decimals);
+ void notationChanged(QDoubleValidator::Notation notation);
+
#ifdef QT3_SUPPORT
public:
QT3_SUPPORT_CONSTRUCTOR QDoubleValidator(QObject * parent, const char *name);
@@ -182,7 +189,7 @@ private:
class Q_GUI_EXPORT QRegExpValidator : public QValidator
{
Q_OBJECT
- Q_PROPERTY(QRegExp regExp READ regExp WRITE setRegExp)
+ Q_PROPERTY(QRegExp regExp READ regExp WRITE setRegExp NOTIFY regExpChanged)
public:
explicit QRegExpValidator(QObject *parent = 0);
@@ -194,6 +201,8 @@ public:
void setRegExp(const QRegExp& rx);
const QRegExp& regExp() const { return r; } // ### make inline for 5.0
+Q_SIGNALS:
+ void regExpChanged(const QRegExp& regExp);
#ifdef QT3_SUPPORT
public:
QT3_SUPPORT_CONSTRUCTOR QRegExpValidator(QObject *parent, const char *name);
diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
index ab103ba836..58b9002222 100644
--- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
+++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
@@ -97,10 +97,6 @@ extern Q_GUI_EXPORT bool qt_cleartype_enabled;
extern bool qt_applefontsmoothing_enabled;
#endif
-#if !defined(QT_MAX_CACHED_GLYPH_SIZE)
-# define QT_MAX_CACHED_GLYPH_SIZE 64
-#endif
-
Q_GUI_EXPORT QImage qt_imageForBrush(int brushStyle, bool invert);
////////////////////////////////// Private Methods //////////////////////////////////////////
@@ -1441,8 +1437,7 @@ void QGL2PaintEngineEx::drawStaticTextItem(QStaticTextItem *textItem)
// don't try to cache huge fonts or vastly transformed fonts
QFontEngine *fontEngine = textItem->fontEngine();
const qreal pixelSize = fontEngine->fontDef.pixelSize;
- if (pixelSize * pixelSize * qAbs(det) < QT_MAX_CACHED_GLYPH_SIZE * QT_MAX_CACHED_GLYPH_SIZE ||
- det < 0.25f || det > 4.f) {
+ if (shouldDrawCachedGlyphs(pixelSize, s->matrix) || det < 0.25f || det > 4.f) {
QFontEngineGlyphCache::Type glyphType = fontEngine->glyphFormat >= 0
? QFontEngineGlyphCache::Type(textItem->fontEngine()->glyphFormat)
: d->glyphCacheType;
@@ -1500,8 +1495,7 @@ void QGL2PaintEngineEx::drawTextItem(const QPointF &p, const QTextItem &textItem
// don't try to cache huge fonts or vastly transformed fonts
const qreal pixelSize = ti.fontEngine->fontDef.pixelSize;
- if (pixelSize * pixelSize * qAbs(det) >= QT_MAX_CACHED_GLYPH_SIZE * QT_MAX_CACHED_GLYPH_SIZE ||
- det < 0.25f || det > 4.f)
+ if (shouldDrawCachedGlyphs(pixelSize, s->matrix) || det < 0.25f || det > 4.f)
drawCached = false;
QFontEngineGlyphCache::Type glyphType = ti.fontEngine->glyphFormat >= 0
diff --git a/src/opengl/qgl_x11.cpp b/src/opengl/qgl_x11.cpp
index 1fd9e373ed..c35488da02 100644
--- a/src/opengl/qgl_x11.cpp
+++ b/src/opengl/qgl_x11.cpp
@@ -347,13 +347,13 @@ static void find_trans_colors()
QGLFormat UNIX/GLX-specific code
*****************************************************************************/
-void* qglx_getProcAddress(const char* procName)
+void (*qglx_getProcAddress(const char* procName))()
{
// On systems where the GL driver is pluggable (like Mesa), we have to use
// the glXGetProcAddressARB extension to resolve other function pointers as
// the symbols wont be in the GL library, but rather in a plugin loaded by
// the GL library.
- typedef void* (*qt_glXGetProcAddressARB)(const char *);
+ typedef void (*(*qt_glXGetProcAddressARB)(const char *))();
static qt_glXGetProcAddressARB glXGetProcAddressARB = 0;
static bool triedResolvingGlxGetProcAddress = false;
if (!triedResolvingGlxGetProcAddress) {
@@ -378,7 +378,7 @@ void* qglx_getProcAddress(const char* procName)
}
}
- void *procAddress = 0;
+ void (*procAddress)() = 0;
if (glXGetProcAddressARB)
procAddress = glXGetProcAddressARB(procName);
@@ -387,7 +387,7 @@ void* qglx_getProcAddress(const char* procName)
if (!procAddress) {
void *handle = dlopen(NULL, RTLD_LAZY);
if (handle) {
- procAddress = dlsym(handle, procName);
+ procAddress = (void (*)())dlsym(handle, procName);
dlclose(handle);
}
}
diff --git a/src/opengl/qglpixelbuffer_x11.cpp b/src/opengl/qglpixelbuffer_x11.cpp
index 9e8beba311..fcd7b521bb 100644
--- a/src/opengl/qglpixelbuffer_x11.cpp
+++ b/src/opengl/qglpixelbuffer_x11.cpp
@@ -93,7 +93,7 @@ static _glXMakeContextCurrent qt_glXMakeContextCurrent = 0;
#define glXGetFBConfigAttrib qt_glXGetFBConfigAttrib
#define glXMakeContextCurrent qt_glXMakeContextCurrent
-extern void* qglx_getProcAddress(const char* procName); // in qgl_x11.cpp
+extern void (*qglx_getProcAddress(const char* procName))(); // in qgl_x11.cpp
static bool qt_resolve_pbuffer_extensions()
{
diff --git a/src/plugins/platforms/xlib/qxlibstatic.cpp b/src/plugins/platforms/xlib/qxlibstatic.cpp
index ee4c463b94..3ba0eb4c32 100644
--- a/src/plugins/platforms/xlib/qxlibstatic.cpp
+++ b/src/plugins/platforms/xlib/qxlibstatic.cpp
@@ -218,8 +218,8 @@ static const char * x11_atomnames = {
\c XFIXES_MAJOR - it is a part of soname and may differ from the Xfixes
version.
*/
-static void* qt_load_library_runtime(const char *library, int vernum,
- int highestVernum, const char *symbol)
+static QFunctionPointer qt_load_library_runtime(const char *library, int vernum,
+ int highestVernum, const char *symbol)
{
QList<int> versions;
// we try to load in the following order:
@@ -234,7 +234,7 @@ static void* qt_load_library_runtime(const char *library, int vernum,
Q_FOREACH(int version, versions) {
QLatin1String libName(library);
QLibrary xfixesLib(libName, version);
- void *ptr = xfixesLib.resolve(symbol);
+ QFunctionPointer ptr = xfixesLib.resolve(symbol);
if (ptr)
return ptr;
}
diff --git a/src/sql/models/qsqlrelationaltablemodel.cpp b/src/sql/models/qsqlrelationaltablemodel.cpp
index f6c401842f..5b0406f4b0 100644
--- a/src/sql/models/qsqlrelationaltablemodel.cpp
+++ b/src/sql/models/qsqlrelationaltablemodel.cpp
@@ -119,6 +119,8 @@ QT_BEGIN_NAMESPACE
returns false.
*/
+class QRelatedTableModel;
+
struct QRelation
{
public:
@@ -135,7 +137,7 @@ struct QRelation
bool isValid();
QSqlRelation rel;
- QSqlTableModel *model;
+ QRelatedTableModel *model;
QHash<QString, QVariant> dictionary;//maps keys to display values
private:
@@ -143,6 +145,15 @@ struct QRelation
bool m_dictInitialized;
};
+class QRelatedTableModel : public QSqlTableModel
+{
+public:
+ QRelatedTableModel(QRelation *rel, QObject *parent = 0, QSqlDatabase db = QSqlDatabase());
+ bool select();
+private:
+ bool firstSelect;
+ QRelation *relation;
+};
/*
A QRelation must be initialized before it is considered valid.
Note: population of the model and dictionary are kept separate
@@ -162,7 +173,7 @@ void QRelation::populateModel()
Q_ASSERT(m_parent != NULL);
if (!model) {
- model = new QSqlTableModel(m_parent, m_parent->database());
+ model = new QRelatedTableModel(this, m_parent, m_parent->database());
model->setTable(rel.tableName());
model->select();
}
@@ -219,6 +230,27 @@ bool QRelation::isValid()
return (rel.isValid() && m_parent != NULL);
}
+
+
+QRelatedTableModel::QRelatedTableModel(QRelation *rel, QObject *parent, QSqlDatabase db) :
+ QSqlTableModel(parent, db), firstSelect(true), relation(rel)
+{
+}
+
+bool QRelatedTableModel::select()
+{
+ if (firstSelect) {
+ firstSelect = false;
+ return QSqlTableModel::select();
+ }
+ relation->clearDictionary();
+ bool res = QSqlTableModel::select();
+ if (res)
+ relation->populateDictionary();
+ return res;
+}
+
+
class QSqlRelationalTableModelPrivate: public QSqlTableModelPrivate
{
Q_DECLARE_PUBLIC(QSqlRelationalTableModel)
diff --git a/src/testlib/testlib.pro b/src/testlib/testlib.pro
index 435036e0c8..a017d33b4a 100644
--- a/src/testlib/testlib.pro
+++ b/src/testlib/testlib.pro
@@ -88,7 +88,7 @@ qpa:mac: {
load(qt_module_config)
-HEADERS += $$QT_SOURCE_TREE/src/testlib/qttestlibversion.h
+HEADERS += $$QT_SOURCE_TREE/src/testlib/qttestversion.h
QMAKE_TARGET_PRODUCT = QTestLib
QMAKE_TARGET_DESCRIPTION = Qt \
diff --git a/src/widgets/platforms/mac/qrawfont_mac.cpp b/src/widgets/platforms/mac/qrawfont_mac.cpp
index df68eb7e7a..40c719a1af 100644
--- a/src/widgets/platforms/mac/qrawfont_mac.cpp
+++ b/src/widgets/platforms/mac/qrawfont_mac.cpp
@@ -55,7 +55,7 @@ void QRawFontPrivate::platformCleanUp()
extern int qt_defaultDpi();
void QRawFontPrivate::platformLoadFromData(const QByteArray &fontData,
- int pixelSize,
+ qreal pixelSize,
QFont::HintingPreference hintingPreference)
{
// Mac OS X ignores it
diff --git a/src/widgets/platforms/win/qrawfont_win.cpp b/src/widgets/platforms/win/qrawfont_win.cpp
index 6c62673b54..d8aa557975 100644
--- a/src/widgets/platforms/win/qrawfont_win.cpp
+++ b/src/widgets/platforms/win/qrawfont_win.cpp
@@ -529,7 +529,8 @@ void QRawFontPrivate::platformCleanUp()
{
if (fontHandle != NULL) {
if (ptrRemoveFontMemResourceEx == NULL) {
- void *func = QSystemLibrary::resolve(QLatin1String("gdi32"), "RemoveFontMemResourceEx");
+ QFunctionPointer func =
+ QSystemLibrary::resolve(QLatin1String("gdi32"), "RemoveFontMemResourceEx");
ptrRemoveFontMemResourceEx =
reinterpret_cast<QRawFontPrivate::PtrRemoveFontMemResourceEx>(func);
}
@@ -545,7 +546,7 @@ void QRawFontPrivate::platformCleanUp()
}
void QRawFontPrivate::platformLoadFromData(const QByteArray &_fontData,
- int pixelSize,
+ qreal pixelSize,
QFont::HintingPreference hintingPreference)
{
QByteArray fontData(_fontData);
@@ -572,7 +573,8 @@ void QRawFontPrivate::platformLoadFromData(const QByteArray &_fontData,
}
if (ptrAddFontMemResourceEx == NULL || ptrRemoveFontMemResourceEx == NULL) {
- void *func = QSystemLibrary::resolve(QLatin1String("gdi32"), "RemoveFontMemResourceEx");
+ QFunctionPointer func =
+ QSystemLibrary::resolve(QLatin1String("gdi32"), "RemoveFontMemResourceEx");
ptrRemoveFontMemResourceEx =
reinterpret_cast<QRawFontPrivate::PtrRemoveFontMemResourceEx>(func);
diff --git a/src/widgets/platforms/x11/qkeymapper_x11.cpp b/src/widgets/platforms/x11/qkeymapper_x11.cpp
index e243716f6a..455840f8b2 100644
--- a/src/widgets/platforms/x11/qkeymapper_x11.cpp
+++ b/src/widgets/platforms/x11/qkeymapper_x11.cpp
@@ -513,7 +513,7 @@ void QKeyMapperPrivate::clearMappings()
// ### ???
// if (keyboardLayoutName.isEmpty())
- // qWarning("Qt: unable to determine keyboard layout, please talk to qt-bugs@trolltech.com"); ?
+ // qWarning("Qt: unable to determine keyboard layout, please talk to qt-info@nokia.com"); ?
keyboardInputLocale = q_getKeyboardLocale(layoutName, variantName);
keyboardInputDirection = keyboardInputLocale.textDirection();
diff --git a/src/widgets/widgets/qtabwidget.h b/src/widgets/widgets/qtabwidget.h
index 447560f332..899b7a5dba 100644
--- a/src/widgets/widgets/qtabwidget.h
+++ b/src/widgets/widgets/qtabwidget.h
@@ -148,6 +148,8 @@ public:
void clear();
+ QTabBar* tabBar() const;
+
public Q_SLOTS:
void setCurrentIndex(int index);
void setCurrentWidget(QWidget *widget);
@@ -165,7 +167,6 @@ protected:
void keyPressEvent(QKeyEvent *);
void paintEvent(QPaintEvent *);
void setTabBar(QTabBar *);
- QTabBar* tabBar() const;
void changeEvent(QEvent *);
bool event(QEvent *);
void initStyleOption(QStyleOptionTabWidgetFrame *option) const;
diff --git a/src/winmain/winmain.pro b/src/winmain/winmain.pro
index b353e8e382..6630d86326 100644
--- a/src/winmain/winmain.pro
+++ b/src/winmain/winmain.pro
@@ -1,7 +1,6 @@
# Additional Qt project file for qtmain lib on Windows
TEMPLATE = lib
TARGET = qtmain
-DESTDIR = $$QMAKE_LIBDIR_QT
QT =
CONFIG += staticlib warn_on
@@ -17,5 +16,6 @@ win32 {
!win32:error("$$_FILE_ is intended only for Windows!")
load(qt_module_config)
+DESTDIR = $$QMAKE_LIBDIR_QT
wince*:QMAKE_POST_LINK =