diff options
author | Bjørn Erik Nilsen <bjorn.nilsen@nokia.com> | 2009-08-07 12:31:58 (GMT) |
---|---|---|
committer | Bjørn Erik Nilsen <bjorn.nilsen@nokia.com> | 2009-08-07 12:31:58 (GMT) |
commit | 103334ced3b0cb6e69a1ed3075d9b81e591f37e9 (patch) | |
tree | c7e36b012a042ce864556f9851cb1220d9f385c5 /src/corelib | |
parent | a4391dfd2aef38e3a3d37bee07900296ced2521c (diff) | |
parent | 490f135caa35831646dac7e00f1c9422cb09aca9 (diff) | |
download | Qt-103334ced3b0cb6e69a1ed3075d9b81e591f37e9.zip Qt-103334ced3b0cb6e69a1ed3075d9b81e591f37e9.tar.gz Qt-103334ced3b0cb6e69a1ed3075d9b81e591f37e9.tar.bz2 |
Merge commit 'qt/master' into kinetic-graphicseffect
Conflicts:
src/gui/graphicsview/graphicsview.pri
src/gui/graphicsview/qgraphicsitem.cpp
src/gui/graphicsview/qgraphicsitem.h
src/gui/graphicsview/qgraphicsitem_p.h
src/gui/graphicsview/qgraphicsscene.cpp
tests/auto/auto.pro
Diffstat (limited to 'src/corelib')
82 files changed, 3385 insertions, 749 deletions
diff --git a/src/corelib/animation/qabstractanimation.cpp b/src/corelib/animation/qabstractanimation.cpp index ced86d2..1d274c9 100644 --- a/src/corelib/animation/qabstractanimation.cpp +++ b/src/corelib/animation/qabstractanimation.cpp @@ -177,17 +177,6 @@ QUnifiedTimer *QUnifiedTimer::instance() return inst; } -void QUnifiedTimer::updateRecentlyStartedAnimations() -{ - if (animationsToStart.isEmpty()) - return; - - animations += animationsToStart; - updateTimer(); //we make sure we start the timer there - - animationsToStart.clear(); -} - void QUnifiedTimer::timerEvent(QTimerEvent *event) { //this is simply the time we last received a tick @@ -195,15 +184,16 @@ void QUnifiedTimer::timerEvent(QTimerEvent *event) if (time.isValid()) lastTick = consistentTiming ? oldLastTick + timingInterval : time.elapsed(); - //we transfer the waiting animations into the "really running" state - updateRecentlyStartedAnimations(); if (event->timerId() == startStopAnimationTimer.timerId()) { startStopAnimationTimer.stop(); + //we transfer the waiting animations into the "really running" state + animations += animationsToStart; + animationsToStart.clear(); if (animations.isEmpty()) { animationTimer.stop(); time = QTime(); - } else { + } else if (!animationTimer.isActive()) { animationTimer.start(timingInterval, this); lastTick = 0; time.start(); @@ -219,27 +209,19 @@ void QUnifiedTimer::timerEvent(QTimerEvent *event) } } -void QUnifiedTimer::updateTimer() -{ - //we delay the call to start and stop for the animation timer so that if you - //stop and start animations in batch you don't stop/start the timer too often. - if (!startStopAnimationTimer.isActive()) - startStopAnimationTimer.start(0, this); // we delay the actual start of the animation -} - void QUnifiedTimer::registerAnimation(QAbstractAnimation *animation) { if (animations.contains(animation) ||animationsToStart.contains(animation)) return; animationsToStart << animation; - updateTimer(); + startStopAnimationTimer.start(0, this); // we delay the check if we should start/stop the global timer } void QUnifiedTimer::unregisterAnimation(QAbstractAnimation *animation) { animations.removeAll(animation); animationsToStart.removeAll(animation); - updateTimer(); + startStopAnimationTimer.start(0, this); // we delay the check if we should start/stop the global timer } diff --git a/src/corelib/animation/qabstractanimation_p.h b/src/corelib/animation/qabstractanimation_p.h index 0d8402e..b281aa2 100644 --- a/src/corelib/animation/qabstractanimation_p.h +++ b/src/corelib/animation/qabstractanimation_p.h @@ -135,11 +135,8 @@ public: protected: void timerEvent(QTimerEvent *); - void updateTimer(); private: - void updateRecentlyStartedAnimations(); - QBasicTimer animationTimer, startStopAnimationTimer; QTime time; int lastTick; diff --git a/src/corelib/animation/qparallelanimationgroup.cpp b/src/corelib/animation/qparallelanimationgroup.cpp index 5e4b0d2..8aa04a4 100644 --- a/src/corelib/animation/qparallelanimationgroup.cpp +++ b/src/corelib/animation/qparallelanimationgroup.cpp @@ -214,7 +214,8 @@ void QParallelAnimationGroup::updateState(QAbstractAnimation::State oldState, d->connectUncontrolledAnimations(); for (int i = 0; i < d->animations.size(); ++i) { QAbstractAnimation *animation = d->animations.at(i); - animation->stop(); + if (oldState == Stopped) + animation->stop(); animation->setDirection(d->direction); animation->start(); } diff --git a/src/corelib/animation/qvariantanimation.cpp b/src/corelib/animation/qvariantanimation.cpp index 48e5ec1..fdd98c2 100644 --- a/src/corelib/animation/qvariantanimation.cpp +++ b/src/corelib/animation/qvariantanimation.cpp @@ -267,7 +267,7 @@ void QVariantAnimationPrivate::setCurrentValueForProgress(const qreal progress) localProgress); qSwap(currentValue, ret); q->updateCurrentValue(currentValue); - if ((connectedSignals & changedSignalMask) && currentValue != ret) { + if ((connectedSignals[0] & changedSignalMask) && currentValue != ret) { //the value has changed emit q->valueChanged(currentValue); } diff --git a/src/corelib/arch/arch.pri b/src/corelib/arch/arch.pri index 20b9227..dd3141a 100644 --- a/src/corelib/arch/arch.pri +++ b/src/corelib/arch/arch.pri @@ -4,6 +4,8 @@ win32:HEADERS += arch/qatomic_windows.h \ mac:HEADERS += arch/qatomic_macosx.h \ arch/qatomic_generic.h +vxworks:HEADERS += arch/qatomic_vxworks.h + !wince*:!win32:!mac:HEADERS += arch/qatomic_alpha.h \ arch/qatomic_avr32.h \ arch/qatomic_ia64.h \ diff --git a/src/corelib/arch/qatomic_arch.h b/src/corelib/arch/qatomic_arch.h index 724cf7e..17e4630 100644 --- a/src/corelib/arch/qatomic_arch.h +++ b/src/corelib/arch/qatomic_arch.h @@ -46,7 +46,9 @@ QT_BEGIN_HEADER #include "QtCore/qglobal.h" -#if defined(QT_ARCH_ALPHA) +#if defined(QT_ARCH_VXWORKS) +# include "QtCore/qatomic_vxworks.h" +#elif defined(QT_ARCH_ALPHA) # include "QtCore/qatomic_alpha.h" #elif defined(QT_ARCH_ARM) # include "QtCore/qatomic_arm.h" diff --git a/src/corelib/arch/qatomic_vxworks.h b/src/corelib/arch/qatomic_vxworks.h new file mode 100644 index 0000000..b441210 --- /dev/null +++ b/src/corelib/arch/qatomic_vxworks.h @@ -0,0 +1,318 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the qmake spec of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QATOMIC_VXWORKS_H +#define QATOMIC_VXWORKS_H + +QT_BEGIN_HEADER + +#if defined(__ppc) +# include <QtCore/qatomic_powerpc.h> +#else // generic implementation with taskLock() + +#if 0 +// we don't want to include the system header here for two function prototypes, +// because it pulls in a _lot_ of stuff that pollutes the global namespace +# include <vxWorksCommon.h> +# include <taskLib.h> +#else +extern "C" int taskLock(); +extern "C" int taskUnlock(); +#endif + + + +QT_BEGIN_NAMESPACE + +#define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_NOT_NATIVE + +inline bool QBasicAtomicInt::isReferenceCountingNative() +{ return false; } +inline bool QBasicAtomicInt::isReferenceCountingWaitFree() +{ return false; } + +#define Q_ATOMIC_INT_TEST_AND_SET_IS_NOT_NATIVE + +inline bool QBasicAtomicInt::isTestAndSetNative() +{ return false; } +inline bool QBasicAtomicInt::isTestAndSetWaitFree() +{ return false; } + +#define Q_ATOMIC_INT_FETCH_AND_STORE_IS_NOT_NATIVE + +inline bool QBasicAtomicInt::isFetchAndStoreNative() +{ return false; } +inline bool QBasicAtomicInt::isFetchAndStoreWaitFree() +{ return false; } + +#define Q_ATOMIC_INT_FETCH_AND_ADD_IS_NOT_NATIVE + +inline bool QBasicAtomicInt::isFetchAndAddNative() +{ return false; } +inline bool QBasicAtomicInt::isFetchAndAddWaitFree() +{ return false; } + +#define Q_ATOMIC_POINTER_TEST_AND_SET_IS_NOT_NATIVE + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetNative() +{ return false; } +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetWaitFree() +{ return false; } + +#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_NOT_NATIVE + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreNative() +{ return false; } +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreWaitFree() +{ return false; } + +#define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_NOT_NATIVE + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddNative() +{ return false; } +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddWaitFree() +{ return false; } + +// Reference counting + +inline bool QBasicAtomicInt::ref() +{ + taskLock(); + bool ret = (++_q_value != 0); + taskUnlock(); + return ret; +} + +inline bool QBasicAtomicInt::deref() +{ + taskLock(); + bool ret = (--_q_value != 0); + taskUnlock(); + return ret; +} + +// Test-and-set for integers + +inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue) +{ + taskLock(); + if (_q_value == expectedValue) { + _q_value = newValue; + taskUnlock(); + return true; + } + taskUnlock(); + return false; +} + +inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +inline bool QBasicAtomicInt::testAndSetAcquire(int expectedValue, int newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +inline bool QBasicAtomicInt::testAndSetRelease(int expectedValue, int newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +// Fetch-and-store for integers + +inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue) +{ + taskLock(); + int returnValue = _q_value; + _q_value = newValue; + taskUnlock(); + return returnValue; +} + +inline int QBasicAtomicInt::fetchAndStoreRelaxed(int newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +inline int QBasicAtomicInt::fetchAndStoreAcquire(int newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +inline int QBasicAtomicInt::fetchAndStoreRelease(int newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +// Fetch-and-add for integers + +inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd) +{ + taskLock(); + int originalValue = _q_value; + _q_value += valueToAdd; + taskUnlock(); + return originalValue; +} + +inline int QBasicAtomicInt::fetchAndAddRelaxed(int valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +inline int QBasicAtomicInt::fetchAndAddAcquire(int valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +inline int QBasicAtomicInt::fetchAndAddRelease(int valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +// Test and set for pointers + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue) +{ + taskLock(); + if (_q_value == expectedValue) { + _q_value = newValue; + taskUnlock(); + return true; + } + taskUnlock(); + return false; +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValue, T *newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetAcquire(T *expectedValue, T *newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelease(T *expectedValue, T *newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +// Fetch and store for pointers + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue) +{ + taskLock(); + T *returnValue = (_q_value); + _q_value = newValue; + taskUnlock(); + return returnValue; +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelaxed(T *newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreAcquire(T *newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelease(T *newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +// Fetch and add for pointers + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd) +{ + taskLock(); + T *returnValue = (_q_value); + _q_value += valueToAdd; + taskUnlock(); + return returnValue; +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelaxed(qptrdiff valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddAcquire(qptrdiff valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelease(qptrdiff valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +QT_END_NAMESPACE + +#endif // generic implementation with taskLock() + +QT_END_HEADER + +#endif // QATOMIC_VXWORKS_H diff --git a/src/corelib/arch/vxworks/arch.pri b/src/corelib/arch/vxworks/arch.pri new file mode 100644 index 0000000..a768618 --- /dev/null +++ b/src/corelib/arch/vxworks/arch.pri @@ -0,0 +1,6 @@ +# +# VxWorks generic +# +*-ppc-* { + SOURCES += qatomic_ppc.s +} diff --git a/src/corelib/arch/vxworks/qatomic_ppc.s b/src/corelib/arch/vxworks/qatomic_ppc.s new file mode 100644 index 0000000..03971e8 --- /dev/null +++ b/src/corelib/arch/vxworks/qatomic_ppc.s @@ -0,0 +1,415 @@ + + .align 2 + .globl q_atomic_test_and_set_int + .globl .q_atomic_test_and_set_int +q_atomic_test_and_set_int: +.q_atomic_test_and_set_int: + lwarx 6,0,3 + xor. 6,6,4 + bne $+12 + stwcx. 5,0,3 + bne- $-16 + subfic 3,6,0 + adde 3,3,6 + blr +LT..q_atomic_test_and_set_int: + .long 0 + .byte 0,9,32,64,0,0,3,0 + .long 0 + .long LT..q_atomic_test_and_set_int-.q_atomic_test_and_set_int + .short 25 + .byte "q_atomic_test_and_set_int" + .align 2 + + .align 2 + .globl q_atomic_test_and_set_acquire_int + .globl .q_atomic_test_and_set_acquire_int +q_atomic_test_and_set_acquire_int: +.q_atomic_test_and_set_acquire_int: + lwarx 6,0,3 + xor. 6,6,4 + bne $+16 + stwcx. 5,0,3 + bne- $-16 + isync + subfic 3,6,0 + adde 3,3,6 + blr +LT..q_atomic_test_and_set_acquire_int: + .long 0 + .byte 0,9,32,64,0,0,3,0 + .long 0 + .long LT..q_atomic_test_and_set_acquire_int-.q_atomic_test_and_set_acquire_int + .short 33 + .byte "q_atomic_test_and_set_acquire_int" + .align 2 + + .align 2 + .globl q_atomic_test_and_set_release_int + .globl .q_atomic_test_and_set_release_int +q_atomic_test_and_set_release_int: +.q_atomic_test_and_set_release_int: + lwarx 6,0,3 + xor. 6,6,4 + bne $+12 + stwcx. 5,0,3 + bne- $-16 + subfic 3,6,0 + adde 3,3,6 + blr +LT..q_atomic_test_and_set_release_int: + .long 0 + .byte 0,9,32,64,0,0,3,0 + .long 0 + .long LT..q_atomic_test_and_set_release_int-.q_atomic_test_and_set_release_int + .short 33 + .byte "q_atomic_test_and_set_release_int" + .align 2 + + .align 2 + .globl q_atomic_test_and_set_ptr + .globl .q_atomic_test_and_set_ptr +q_atomic_test_and_set_ptr: +.q_atomic_test_and_set_ptr: + lwarx 6,0,3 + xor. 6,6,4 + bne $+12 + stwcx. 5,0,3 + bne- $-16 + subfic 3,6,0 + adde 3,3,6 + blr +LT..q_atomic_test_and_set_ptr: + .long 0 + .byte 0,9,32,64,0,0,3,0 + .long 0 + .long LT..q_atomic_test_and_set_ptr-.q_atomic_test_and_set_ptr + .short 25 + .byte "q_atomic_test_and_set_ptr" + .align 2 + + .align 2 + .globl q_atomic_test_and_set_acquire_ptr + .globl .q_atomic_test_and_set_acquire_ptr +q_atomic_test_and_set_acquire_ptr: +.q_atomic_test_and_set_acquire_ptr: + lwarx 6,0,3 + xor. 6,6,4 + bne $+16 + stwcx. 5,0,3 + bne- $-16 + isync + subfic 3,6,0 + adde 3,3,6 + blr +LT..q_atomic_test_and_set_acquire_ptr: + .long 0 + .byte 0,9,32,64,0,0,3,0 + .long 0 + .long LT..q_atomic_test_and_set_acquire_ptr-.q_atomic_test_and_set_acquire_ptr + .short 25 + .byte "q_atomic_test_and_set_acquire_ptr" + .align 2 + + .align 2 + .globl q_atomic_test_and_set_release_ptr + .globl .q_atomic_test_and_set_release_ptr +q_atomic_test_and_set_release_ptr: +.q_atomic_test_and_set_release_ptr: + lwarx 6,0,3 + xor. 6,6,4 + bne $+12 + stwcx. 5,0,3 + bne- $-16 + subfic 3,6,0 + adde 3,3,6 + blr +LT..q_atomic_test_and_set_release_ptr: + .long 0 + .byte 0,9,32,64,0,0,3,0 + .long 0 + .long LT..q_atomic_test_and_set_release_ptr-.q_atomic_test_and_set_release_ptr + .short 33 + .byte "q_atomic_test_and_set_release_ptr" + .align 2 + + .align 2 + .globl q_atomic_increment + .globl .q_atomic_increment +q_atomic_increment: +.q_atomic_increment: + lwarx 4,0,3 + addi 4,4,1 + stwcx. 4,0,3 + bne- $-12 + mr 3,4 + blr +LT..q_atomic_increment: + .long 0 + .byte 0,9,32,64,0,0,1,0 + .long 0 + .long LT..q_atomic_increment-.q_atomic_increment + .short 18 + .byte "q_atomic_increment" + .align 2 + + .align 2 + .globl q_atomic_decrement + .globl .q_atomic_decrement +q_atomic_decrement: +.q_atomic_decrement: + lwarx 4,0,3 + subi 4,4,1 + stwcx. 4,0,3 + bne- $-12 + mr 3,4 + blr +LT..q_atomic_decrement: + .long 0 + .byte 0,9,32,64,0,0,1,0 + .long 0 + .long LT..q_atomic_decrement-.q_atomic_decrement + .short 18 + .byte "q_atomic_decrement" + .align 2 + + .align 2 + .globl q_atomic_set_int + .globl .q_atomic_set_int +q_atomic_set_int: +.q_atomic_set_int: + lwarx 5,0,3 + stwcx. 4,0,3 + bne- $-8 + mr 3,5 + blr +LT..q_atomic_set_int: + .long 0 + .byte 0,9,32,64,0,0,2,0 + .long 0 + .long LT..q_atomic_set_int-.q_atomic_set_int + .short 16 + .byte "q_atomic_set_int" + .align 2 + + .align 2 + .globl q_atomic_fetch_and_store_acquire_int + .globl .q_atomic_fetch_and_store_acquire_int +q_atomic_fetch_and_store_acquire_int: +.q_atomic_fetch_and_store_acquire_int: + lwarx 5,0,3 + stwcx. 4,0,3 + bne- $-8 + isync + mr 3,5 + blr +LT..q_atomic_fetch_and_store_acquire_int: + .long 0 + .byte 0,9,32,64,0,0,2,0 + .long 0 + .long LT..q_atomic_fetch_and_store_acquire_int-.q_atomic_fetch_and_store_acquire_int + .short 16 + .byte "q_atomic_fetch_and_store_acquire_int" + .align 2 + + .align 2 + .globl q_atomic_fetch_and_store_release_int + .globl .q_atomic_fetch_and_store_release_int +q_atomic_fetch_and_store_release_int: +.q_atomic_fetch_and_store_release_int: + lwarx 5,0,3 + stwcx. 4,0,3 + bne- $-8 + mr 3,5 + blr +LT..q_atomic_fetch_and_store_release_int: + .long 0 + .byte 0,9,32,64,0,0,2,0 + .long 0 + .long LT..q_atomic_fetch_and_store_release_int-.q_atomic_fetch_and_store_release_int + .short 16 + .byte "q_atomic_fetch_and_store_release_int" + .align 2 + + .align 2 + .globl q_atomic_set_ptr + .globl .q_atomic_set_ptr +q_atomic_set_ptr: +.q_atomic_set_ptr: + lwarx 5,0,3 + stwcx. 4,0,3 + bne- $-8 + mr 3,5 + blr +LT..q_atomic_set_ptr: + .long 0 + .byte 0,9,32,64,0,0,2,0 + .long 0 + .long LT..q_atomic_set_ptr-.q_atomic_set_ptr + .short 16 + .byte "q_atomic_set_ptr" + .align 2 + + .align 2 + .globl q_atomic_fetch_and_store_acquire_ptr + .globl .q_atomic_fetch_and_store_acquire_ptr +q_atomic_fetch_and_store_acquire_ptr: +.q_atomic_fetch_and_store_acquire_ptr: + lwarx 5,0,3 + stwcx. 4,0,3 + bne- $-8 + isync + mr 3,5 + blr +LT..q_atomic_fetch_and_store_acquire_ptr: + .long 0 + .byte 0,9,32,64,0,0,2,0 + .long 0 + .long LT..q_atomic_fetch_and_store_acquire_ptr-.q_atomic_fetch_and_store_acquire_ptr + .short 16 + .byte "q_atomic_fetch_and_store_acquire_ptr" + .align 2 + + .align 2 + .globl q_atomic_fetch_and_store_release_ptr + .globl .q_atomic_fetch_and_store_release_ptr +q_atomic_fetch_and_store_release_ptr: +.q_atomic_fetch_and_store_release_ptr: + lwarx 5,0,3 + stwcx. 4,0,3 + bne- $-8 + mr 3,5 + blr +LT..q_atomic_fetch_and_store_release_ptr: + .long 0 + .byte 0,9,32,64,0,0,2,0 + .long 0 + .long LT..q_atomic_fetch_and_store_release_ptr-.q_atomic_fetch_and_store_release_ptr + .short 16 + .byte "q_atomic_fetch_and_store_release_ptr" + .align 2 + + .align 2 + .globl q_atomic_fetch_and_add_int + .globl .q_atomic_fetch_and_add_int +q_atomic_fetch_and_add_int: +.q_atomic_fetch_and_add_int: + lwarx 5,0,3 + add 6,4,5 + stwcx. 6,0,3 + bne- $-12 + mr 3,5 + blr +LT..q_atomic_fetch_and_add_int: + .long 0 + .byte 0,9,32,64,0,0,1,0 + .long 0 + .long LT..q_atomic_fetch_and_add_int-.q_atomic_fetch_and_add_int + .short 18 + .byte "q_atomic_fetch_and_add_int" + .align 2 + + .align 2 + .globl q_atomic_fetch_and_add_acquire_int + .globl .q_atomic_fetch_and_add_acquire_int +q_atomic_fetch_and_add_acquire_int: +.q_atomic_fetch_and_add_acquire_int: + lwarx 5,0,3 + add 6,4,5 + stwcx. 6,0,3 + bne- $-12 + isync + mr 3,5 + blr +LT..q_atomic_fetch_and_add_acquire_int: + .long 0 + .byte 0,9,32,64,0,0,1,0 + .long 0 + .long LT..q_atomic_fetch_and_add_acquire_int-.q_atomic_fetch_and_add_acquire_int + .short 18 + .byte "q_atomic_fetch_and_add_acquire_int" + .align 2 + + .align 2 + .globl q_atomic_fetch_and_add_release_int + .globl .q_atomic_fetch_and_add_release_int +q_atomic_fetch_and_add_release_int: +.q_atomic_fetch_and_add_release_int: + lwarx 5,0,3 + add 6,4,5 + stwcx. 6,0,3 + bne- $-12 + mr 3,5 + blr +LT..q_atomic_fetch_and_add_release_int: + .long 0 + .byte 0,9,32,64,0,0,1,0 + .long 0 + .long LT..q_atomic_fetch_and_add_release_int-.q_atomic_fetch_and_add_release_int + .short 34 + .byte "q_atomic_fetch_and_add_release_int" + .align 2 + + .align 2 + .globl q_atomic_fetch_and_add_ptr + .globl .q_atomic_fetch_and_add_ptr +q_atomic_fetch_and_add_ptr: +.q_atomic_fetch_and_add_ptr: + lwarx 5,0,3 + add 6,4,5 + stwcx. 6,0,3 + bne- $-12 + mr 3,5 + blr +LT..q_atomic_fetch_and_add_ptr: + .long 0 + .byte 0,9,32,64,0,0,1,0 + .long 0 + .long LT..q_atomic_fetch_and_add_ptr-.q_atomic_fetch_and_add_ptr + .short 26 + .byte "q_atomic_fetch_and_add_ptr" + .align 2 + + .align 2 + .globl q_atomic_fetch_and_add_acquire_ptr + .globl .q_atomic_fetch_and_add_acquire_ptr +q_atomic_fetch_and_add_acquire_ptr: +.q_atomic_fetch_and_add_acquire_ptr: + lwarx 5,0,3 + add 6,4,5 + stwcx. 6,0,3 + bne- $-12 + isync + mr 3,5 + blr +LT..q_atomic_fetch_and_add_acquire_ptr: + .long 0 + .byte 0,9,32,64,0,0,1,0 + .long 0 + .long LT..q_atomic_fetch_and_add_acquire_ptr-.q_atomic_fetch_and_add_acquire_ptr + .short 34 + .byte "q_atomic_fetch_and_add_acquire_ptr" + .align 2 + + .align 2 + .globl q_atomic_fetch_and_add_release_ptr + .globl .q_atomic_fetch_and_add_release_ptr +q_atomic_fetch_and_add_release_ptr: +.q_atomic_fetch_and_add_release_ptr: + lwarx 5,0,3 + add 6,4,5 + stwcx. 6,0,3 + bne- $-12 + mr 3,5 + blr +LT..q_atomic_fetch_and_add_release_ptr: + .long 0 + .byte 0,9,32,64,0,0,1,0 + .long 0 + .long LT..q_atomic_fetch_and_add_release_ptr-.q_atomic_fetch_and_add_release_ptr + .short 34 + .byte "q_atomic_fetch_and_add_release_ptr" + .align 2 + +_section_.text: + .long _section_.text diff --git a/src/corelib/codecs/qiconvcodec.cpp b/src/corelib/codecs/qiconvcodec.cpp index 188ac8c..7f89a8f 100644 --- a/src/corelib/codecs/qiconvcodec.cpp +++ b/src/corelib/codecs/qiconvcodec.cpp @@ -52,7 +52,7 @@ // unistd.h is needed for the _XOPEN_UNIX macro #include <unistd.h> -#if defined(_XOPEN_UNIX) && !defined(Q_OS_QNX6) && !defined(Q_OS_OSF) +#if defined(_XOPEN_UNIX) && !defined(Q_OS_QNX) && !defined(Q_OS_OSF) # include <langinfo.h> #endif @@ -455,7 +455,7 @@ iconv_t QIconvCodec::createIconv_t(const char *to, const char *from) char *codeset = 0; #endif -#if defined(_XOPEN_UNIX) && !defined(Q_OS_QNX6) && !defined(Q_OS_OSF) +#if defined(_XOPEN_UNIX) && !defined(Q_OS_QNX) && !defined(Q_OS_OSF) if (cd == (iconv_t) -1) { codeset = nl_langinfo(CODESET); if (codeset) diff --git a/src/corelib/codecs/qtextcodec.cpp b/src/corelib/codecs/qtextcodec.cpp index f49e34a..4b774d7 100644 --- a/src/corelib/codecs/qtextcodec.cpp +++ b/src/corelib/codecs/qtextcodec.cpp @@ -84,7 +84,7 @@ #include <stdlib.h> #include <ctype.h> #include <locale.h> -#if defined (_XOPEN_UNIX) && !defined(Q_OS_QNX6) && !defined(Q_OS_OSF) +#if defined (_XOPEN_UNIX) && !defined(Q_OS_QNX) && !defined(Q_OS_OSF) #include <langinfo.h> #endif @@ -532,7 +532,7 @@ static void setupLocaleMapper() localeMapper = QTextCodec::codecForName("System"); #endif -#if defined (_XOPEN_UNIX) && !defined(Q_OS_QNX6) && !defined(Q_OS_OSF) +#if defined (_XOPEN_UNIX) && !defined(Q_OS_QNX) && !defined(Q_OS_OSF) if (!localeMapper) { char *charset = nl_langinfo (CODESET); if (charset) diff --git a/src/corelib/concurrent/qtconcurrentiteratekernel.cpp b/src/corelib/concurrent/qtconcurrentiteratekernel.cpp index ee1ed3a..d0a37de 100644 --- a/src/corelib/concurrent/qtconcurrentiteratekernel.cpp +++ b/src/corelib/concurrent/qtconcurrentiteratekernel.cpp @@ -52,6 +52,8 @@ #include <qt_windows.h> #endif +#include "private/qfunctions_p.h" + #ifndef QT_NO_CONCURRENT diff --git a/src/corelib/concurrent/qtconcurrentthreadengine.h b/src/corelib/concurrent/qtconcurrentthreadengine.h index 1f359fc..2f610de 100644 --- a/src/corelib/concurrent/qtconcurrentthreadengine.h +++ b/src/corelib/concurrent/qtconcurrentthreadengine.h @@ -238,9 +238,11 @@ protected: template <typename T> class ThreadEngineStarter : public ThreadEngineStarterBase<T> { + typedef ThreadEngineStarterBase<T> Base; + typedef ThreadEngine<T> TypedThreadEngine; public: - ThreadEngineStarter(ThreadEngine<T> *threadEngine) - :ThreadEngineStarterBase<T>(threadEngine) {} + ThreadEngineStarter(TypedThreadEngine *eng) + : Base(eng) { } T startBlocking() { diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp index f7d6514..63941ef 100644 --- a/src/corelib/global/qglobal.cpp +++ b/src/corelib/global/qglobal.cpp @@ -62,6 +62,10 @@ # endif #endif +#if defined(Q_OS_VXWORKS) +# include <envLib.h> +#endif + #ifdef Q_CC_MWERKS #include <CoreServices/CoreServices.h> #endif @@ -1079,7 +1083,7 @@ bool qSharedBuild() \value WV_XP Windows XP (operating system version 5.1) \value WV_2003 Windows Server 2003, Windows Server 2003 R2, Windows Home Server, Windows XP Professional x64 Edition (operating system version 5.2) \value WV_VISTA Windows Vista, Windows Server 2008 (operating system version 6.0) - \value WV_WINDOWS7 Windows 7 (operating system version 6.1) + \value WV_WINDOWS7 Windows 7, Windows Server 2008 R2 (operating system version 6.1) Alternatively, you may use the following macros which correspond directly to the Windows operating system version number: @@ -1088,7 +1092,7 @@ bool qSharedBuild() \value WV_5_1 Operating system version 5.1, corresponds to Windows XP \value WV_5_2 Operating system version 5.2, corresponds to Windows Server 2003, Windows Server 2003 R2, Windows Home Server, and Windows XP Professional x64 Edition \value WV_6_0 Operating system version 6.0, corresponds to Windows Vista and Windows Server 2008 - \value WV_6_1 Operating system version 6.1, corresponds to Windows 7 + \value WV_6_1 Operating system version 6.1, corresponds to Windows 7 and Windows Server 2008 R2 CE-based versions: @@ -1344,14 +1348,7 @@ bool qSharedBuild() \macro Q_OS_QNX \relates <QtGlobal> - Defined on QNX. -*/ - -/*! - \macro Q_OS_QNX6 - \relates <QtGlobal> - - Defined on QNX RTP 6.1. + Defined on QNX Neutrino. */ /*! @@ -1914,7 +1911,7 @@ QString qt_error_string(int errorCode) if (ret.isEmpty() && errorCode == ERROR_MOD_NOT_FOUND) ret = QString::fromLatin1("The specified module could not be found."); -#elif !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && _POSIX_VERSION >= 200112L && !defined(Q_OS_INTEGRITY) +#elif !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && _POSIX_VERSION >= 200112L && !defined(Q_OS_INTEGRITY) && !defined(Q_OS_QNX) QByteArray buf(1024, '\0'); strerror_r(errorCode, buf.data(), buf.size()); diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index 7b16dff..1711f16 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -238,8 +238,6 @@ namespace QT_NAMESPACE {} #elif defined(__DGUX__) # define Q_OS_DGUX #elif defined(__QNXNTO__) -# define Q_OS_QNX6 -#elif defined(__QNX__) # define Q_OS_QNX #elif defined(_SEQUENT_) # define Q_OS_DYNIX @@ -251,6 +249,8 @@ namespace QT_NAMESPACE {} # define Q_OS_UNIXWARE #elif defined(__INTEGRITY) # define Q_OS_INTEGRITY +#elif defined(VXWORKS) /* there is no "real" VxWorks define - this has to be set in the mkspec! */ +# define Q_OS_VXWORKS #elif defined(__MAKEDEPEND__) #else # error "Qt has not been ported to this OS - talk to qt-bugs@trolltech.com" @@ -279,7 +279,7 @@ namespace QT_NAMESPACE {} # endif #endif -#if defined(Q_OS_MAC64) && !defined(QT_MAC_USE_COCOA) +#if defined(Q_OS_MAC64) && !defined(QT_MAC_USE_COCOA) && !defined(QT_BUILD_QMAKE) #error "You are building a 64-bit application, but using a 32-bit version of Qt. Check your build configuration." #endif @@ -311,18 +311,11 @@ namespace QT_NAMESPACE {} # if !defined(MAC_OS_X_VERSION_10_6) # define MAC_OS_X_VERSION_10_6 MAC_OS_X_VERSION_10_5 + 1 # endif -# if (MAC_OS_X_VERSION_MAX_ALLOWED == MAC_OS_X_VERSION_10_6) -# warning "Support for this version of Mac OS X is still preliminary" -# endif # if (MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_6) -# error "This version of Mac OS X is unsupported" +# warning "This version of Mac OS X is unsupported" # endif #endif -#ifdef QT_MAC_USE_COCOA -#define QT_MAC_NO_QUICKDRAW 1 -#endif - #ifdef __LSB_VERSION__ # if __LSB_VERSION__ < 40 # error "This version of the Linux Standard Base is unsupported" @@ -429,25 +422,6 @@ namespace QT_NAMESPACE {} #elif defined(__WATCOMC__) # define Q_CC_WAT -# if defined(Q_OS_QNX4) -/* compiler flags */ -# define Q_TYPENAME -# define Q_NO_BOOL_TYPE -# define Q_CANNOT_DELETE_CONSTANT -# define mutable -/* ??? */ -# define Q_BROKEN_TEMPLATE_SPECIALIZATION -/* no template classes in QVariant */ -# define QT_NO_TEMPLATE_VARIANT -/* Wcc does not fill in functions needed by valuelists, maps, and - valuestacks implicitly */ -# define Q_FULL_TEMPLATE_INSTANTIATION -/* can we just compare the structures? */ -# define Q_FULL_TEMPLATE_INSTANTIATION_MEMCMP -/* these are not useful to our customers */ -# define QT_NO_QWS_MULTIPROCESS -# define QT_NO_QWS_CURSOR -# endif #elif defined(__CC_ARM) # define Q_CC_RVCT @@ -615,6 +589,13 @@ namespace QT_NAMESPACE {} # elif defined(__ghs) # define Q_CC_GHS +# elif defined(__DCC__) +# define Q_CC_DIAB +# undef Q_NO_BOOL_TYPE +# if !defined(__bool) +# define Q_NO_BOOL_TYPE +# endif + /* The UnixWare 7 UDK compiler is based on EDG and does define __EDG__ */ # elif defined(__USLC__) && defined(__SCO_VERSION__) # define Q_CC_USLC @@ -646,6 +627,11 @@ namespace QT_NAMESPACE {} # endif # endif +/* VxWorks' DIAB toolchain has an additional EDG type C++ compiler + (see __DCC__ above). This one is for C mode files (__EDG is not defined) */ +#elif defined(_DIAB_TOOL) +# define Q_CC_DIAB + /* Never tested! */ #elif defined(__HIGHC__) # define Q_CC_HIGHC @@ -657,9 +643,7 @@ namespace QT_NAMESPACE {} in which case _BOOL is not defined this is the default in 4.2 compatibility mode triggered by -compat=4 */ # if __SUNPRO_CC >= 0x500 -# if __SUNPRO_CC < 0x570 -# define QT_NO_TEMPLATE_TEMPLATE_PARAMETERS -# endif +# define QT_NO_TEMPLATE_TEMPLATE_PARAMETERS /* see http://developers.sun.com/sunstudio/support/Ccompare.html */ # if __SUNPRO_CC >= 0x590 # define Q_ALIGNOF(type) __alignof__(type) @@ -668,6 +652,9 @@ namespace QT_NAMESPACE {} // using CC 5.9: Warning: attribute visibility is unsupported and will be skipped.. //# define Q_DECL_EXPORT __attribute__((__visibility__("default"))) # endif +# if __SUNPRO_CC < 0x5a0 +# define Q_NO_TEMPLATE_FRIENDS +# endif # if !defined(_BOOL) # define Q_NO_BOOL_TYPE # endif @@ -1113,6 +1100,15 @@ class QDataStream; # define QT_NO_COP #endif +#if defined(Q_OS_VXWORKS) +# define QT_NO_CRASHHANDLER // no popen +# define QT_NO_PROCESS // no exec*, no fork +# define QT_NO_LPR +# define QT_NO_SHAREDMEMORY // only POSIX, no SysV and in the end... +# define QT_NO_SYSTEMSEMAPHORE // not needed at all in a flat address space +# define QT_NO_QWS_MULTIPROCESS // no processes +#endif + # include <QtCore/qfeatures.h> #define QT_SUPPORTS(FEATURE) (!defined(QT_NO_##FEATURE)) @@ -1177,6 +1173,11 @@ class QDataStream; # else # define Q_OPENGL_EXPORT Q_DECL_IMPORT # endif +# if defined(QT_BUILD_MULTIMEDIA_LIB) +# define Q_MULTIMEDIA_EXPORT Q_DECL_EXPORT +# else +# define Q_MULTIMEDIA_EXPORT Q_DECL_IMPORT +# endif # if defined(QT_BUILD_OPENVG_LIB) # define Q_OPENVG_EXPORT Q_DECL_EXPORT # else @@ -1221,6 +1222,7 @@ class QDataStream; # define Q_SVG_EXPORT Q_DECL_IMPORT # define Q_CANVAS_EXPORT Q_DECL_IMPORT # define Q_OPENGL_EXPORT Q_DECL_IMPORT +# define Q_MULTIMEDIA_EXPORT Q_DECL_IMPORT # define Q_OPENVG_EXPORT Q_DECL_IMPORT # define Q_XML_EXPORT Q_DECL_IMPORT # define Q_XMLPATTERNS_EXPORT Q_DECL_IMPORT @@ -1247,6 +1249,7 @@ class QDataStream; # define Q_NETWORK_EXPORT Q_DECL_EXPORT # define Q_SVG_EXPORT Q_DECL_EXPORT # define Q_OPENGL_EXPORT Q_DECL_EXPORT +# define Q_MULTIMEDIA_EXPORT Q_DECL_EXPORT # define Q_OPENVG_EXPORT Q_DECL_EXPORT # define Q_XML_EXPORT Q_DECL_EXPORT # define Q_XMLPATTERNS_EXPORT Q_DECL_EXPORT @@ -1260,6 +1263,7 @@ class QDataStream; # define Q_NETWORK_EXPORT # define Q_SVG_EXPORT # define Q_OPENGL_EXPORT +# define Q_MULTIMEDIA_EXPORT # define Q_XML_EXPORT # define Q_XMLPATTERNS_EXPORT # define Q_SCRIPT_EXPORT @@ -1555,7 +1559,7 @@ Q_CORE_EXPORT void qt_check_pointer(const char *, int); # define Q_CHECK_PTR(p) #endif -#if (defined(Q_CC_GNU) && !defined(Q_OS_SOLARIS)) || defined(Q_CC_HPACC) +#if (defined(Q_CC_GNU) && !defined(Q_OS_SOLARIS)) || defined(Q_CC_HPACC) || defined(Q_CC_DIAB) # define Q_FUNC_INFO __PRETTY_FUNCTION__ #elif defined(_MSC_VER) /* MSVC 2002 doesn't have __FUNCSIG__ nor can it handle QT_STRINGIFY. */ @@ -2145,6 +2149,17 @@ inline const QForeachContainer<T> *qForeachContainer(const QForeachContainerBase qForeachContainer(&_container_, true ? 0 : qForeachPointer(container))->brk; \ --qForeachContainer(&_container_, true ? 0 : qForeachPointer(container))->brk) +#elif defined(Q_CC_DIAB) +// VxWorks DIAB generates unresolvable symbols, if container is a function call +# define Q_FOREACH(variable,container) \ + if(0){}else \ + for (const QForeachContainerBase &_container_ = qForeachContainerNew(container); \ + qForeachContainer(&_container_, (__typeof__(container) *) 0)->condition(); \ + ++qForeachContainer(&_container_, (__typeof__(container) *) 0)->i) \ + for (variable = *qForeachContainer(&_container_, (__typeof__(container) *) 0)->i; \ + qForeachContainer(&_container_, (__typeof__(container) *) 0)->brk; \ + --qForeachContainer(&_container_, (__typeof__(container) *) 0)->brk) + #else # define Q_FOREACH(variable, container) \ for (const QForeachContainerBase &_container_ = qForeachContainerNew(container); \ @@ -2298,12 +2313,14 @@ QT3_SUPPORT Q_CORE_EXPORT const char *qInstallPathSysconf(); #define QT_MODULE_DBUS 0x08000 #define QT_MODULE_SCRIPTTOOLS 0x10000 #define QT_MODULE_OPENVG 0x20000 +#define QT_MODULE_MULTIMEDIA 0x40000 /* Qt editions */ #define QT_EDITION_CONSOLE (QT_MODULE_CORE \ | QT_MODULE_NETWORK \ | QT_MODULE_SQL \ | QT_MODULE_SCRIPT \ + | QT_MODULE_MULTIMEDIA \ | QT_MODULE_XML \ | QT_MODULE_XMLPATTERNS \ | QT_MODULE_TEST \ @@ -2319,6 +2336,7 @@ QT3_SUPPORT Q_CORE_EXPORT const char *qInstallPathSysconf(); | QT_MODULE_OPENGL \ | QT_MODULE_OPENVG \ | QT_MODULE_SQL \ + | QT_MODULE_MULTIMEDIA \ | QT_MODULE_XML \ | QT_MODULE_XMLPATTERNS \ | QT_MODULE_SCRIPT \ @@ -2367,6 +2385,9 @@ QT_LICENSED_MODULE(OpenVG) #if (QT_EDITION & QT_MODULE_SQL) QT_LICENSED_MODULE(Sql) #endif +#if (QT_EDITION & QT_MODULE_MULTIMEDIA) +QT_LICENSED_MODULE(Multimedia) +#endif #if (QT_EDITION & QT_MODULE_XML) QT_LICENSED_MODULE(Xml) #endif @@ -2421,6 +2442,17 @@ QT_LICENSED_MODULE(DBus) # define QT_NO_CONCURRENT_FILTER #endif +#ifdef Q_OS_QNX +// QNX doesn't have SYSV style shared memory. Multiprocess QWS apps, +// shared fonts and QSystemSemaphore + QSharedMemory are not available +# define QT_NO_QWS_MULTIPROCESS +# define QT_NO_QWS_SHARE_FONTS +# define QT_NO_SYSTEMSEMAPHORE +# define QT_NO_SHAREDMEMORY +// QNX currently doesn't support forking in a thread, so disable QProcess +# define QT_NO_PROCESS +#endif + QT_END_NAMESPACE QT_END_HEADER diff --git a/src/corelib/global/qnamespace.h b/src/corelib/global/qnamespace.h index 834ad1a..1366c08 100644 --- a/src/corelib/global/qnamespace.h +++ b/src/corelib/global/qnamespace.h @@ -1406,6 +1406,21 @@ public: ImCurrentSelection }; + enum InputMethodHint { + ImhNone = 0x0, + ImhHiddenText = 0x1, + ImhNumbersOnly = 0x2, + ImhUppercaseOnly = 0x4, + ImhLowercaseOnly = 0x8, + ImhNoAutoUppercase = 0x10, + ImhPreferNumbers = 0x20, + ImhPreferUppercase = 0x40, + ImhPreferLowercase = 0x80, + ImhNoPredictiveText = 0x100, + ImhDialableCharactersOnly = 0x200 + }; + Q_DECLARE_FLAGS(InputMethodHints, InputMethodHint) + enum ToolButtonStyle { ToolButtonIconOnly, ToolButtonTextOnly, @@ -1596,6 +1611,7 @@ Q_DECLARE_OPERATORS_FOR_FLAGS(Qt::ItemFlags) Q_DECLARE_OPERATORS_FOR_FLAGS(Qt::MatchFlags) Q_DECLARE_OPERATORS_FOR_FLAGS(Qt::TextInteractionFlags) Q_DECLARE_OPERATORS_FOR_FLAGS(Qt::TouchPointStates) +Q_DECLARE_OPERATORS_FOR_FLAGS(Qt::InputMethodHints) typedef bool (*qInternalCallback)(void **); diff --git a/src/corelib/io/io.pri b/src/corelib/io/io.pri index 5033b21..bd41f5e 100644 --- a/src/corelib/io/io.pri +++ b/src/corelib/io/io.pri @@ -65,7 +65,10 @@ win32 { SOURCES += io/qfsfileengine_unix.cpp SOURCES += io/qfsfileengine_iterator_unix.cpp SOURCES += io/qprocess_unix.cpp - mac:SOURCES += io/qsettings_mac.cpp + macx-*: { + HEADERS += io/qfilesystemwatcher_fsevents_p.h + SOURCES += io/qsettings_mac.cpp io/qfilesystemwatcher_fsevents.cpp + } linux-*:{ SOURCES += \ diff --git a/src/corelib/io/qdatastream.cpp b/src/corelib/io/qdatastream.cpp index 244299c..1023868 100644 --- a/src/corelib/io/qdatastream.cpp +++ b/src/corelib/io/qdatastream.cpp @@ -362,17 +362,19 @@ QDataStream::~QDataStream() /*! \fn QIODevice *QDataStream::device() const - Returns the I/O device currently set. + Returns the I/O device currently set, or 0 if no + device is currently set. - \sa setDevice(), unsetDevice() + \sa setDevice() */ /*! void QDataStream::setDevice(QIODevice *d) - Sets the I/O device to \a d. + Sets the I/O device to \a d, which can be 0 + to unset to current I/O device. - \sa device(), unsetDevice() + \sa device() */ void QDataStream::setDevice(QIODevice *d) diff --git a/src/corelib/io/qdiriterator.cpp b/src/corelib/io/qdiriterator.cpp index 3bfea65..30d2558 100644 --- a/src/corelib/io/qdiriterator.cpp +++ b/src/corelib/io/qdiriterator.cpp @@ -309,17 +309,11 @@ bool QDirIteratorPrivate::matchesFilters(const QString &fileName, const QFileInf || (!fi.exists() && fi.isSymLink()))) return false; - - if (!includeSystem && !dotOrDotDot && ((fi.exists() && !fi.isFile() && !fi.isDir() && !fi.isSymLink()) - || (!fi.exists() && fi.isSymLink()))) { - return false; - } - // skip directories const bool skipDirs = !(filters & (QDir::Dirs | QDir::AllDirs)); if (skipDirs && fi.isDir()) { - if (!(includeHidden && !dotOrDotDot && fi.isHidden()) - || (includeSystem && !fi.exists() && fi.isSymLink())) + if (!((includeHidden && !dotOrDotDot && fi.isHidden()) + || (includeSystem && !fi.exists() && fi.isSymLink()))) return false; } diff --git a/src/corelib/io/qfilesystemwatcher.cpp b/src/corelib/io/qfilesystemwatcher.cpp index b321644..27fe1c2 100644 --- a/src/corelib/io/qfilesystemwatcher.cpp +++ b/src/corelib/io/qfilesystemwatcher.cpp @@ -58,6 +58,9 @@ # include "qfilesystemwatcher_inotify_p.h" # include "qfilesystemwatcher_dnotify_p.h" #elif defined(Q_OS_FREEBSD) || defined(Q_OS_MAC) +# if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5) +# include "qfilesystemwatcher_fsevents_p.h" +# endif //MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5) # include "qfilesystemwatcher_kqueue_p.h" #endif @@ -243,7 +246,12 @@ QFileSystemWatcherEngine *QFileSystemWatcherPrivate::createNativeEngine() eng = QDnotifyFileSystemWatcherEngine::create(); return eng; #elif defined(Q_OS_FREEBSD) || defined(Q_OS_MAC) - return QKqueueFileSystemWatcherEngine::create(); +# if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5) + if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5) + return QFSEventsFileSystemWatcherEngine::create(); + else +# endif + return QKqueueFileSystemWatcherEngine::create(); #else return 0; #endif @@ -376,15 +384,17 @@ void QFileSystemWatcherPrivate::_q_directoryChanged(const QString &path, bool re \note The act of monitoring files and directories for modifications consumes system resources. This implies there is a limit to the number of files and directories your process can - monitor simultaneously. On Mac OS and all BSD variants, for + monitor simultaneously. On Mac OS X 10.4 and all BSD variants, for example, an open file descriptor is required for each monitored - file. The system limits the number of open file descriptors to 256 + file. Some system limits the number of open file descriptors to 256 by default. This means that addPath() and addPaths() will fail if your process tries to add more than 256 files or directories to the file system monitor. Also note that your process may have other file descriptors open in addition to the ones for files being monitored, and these other open descriptors also count in - the total. + the total. Mac OS X 10.5 and up use a different backend and do not + suffer from this issue. + \sa QFile, QDir */ diff --git a/src/corelib/io/qfilesystemwatcher_fsevents.cpp b/src/corelib/io/qfilesystemwatcher_fsevents.cpp new file mode 100644 index 0000000..cb276b7 --- /dev/null +++ b/src/corelib/io/qfilesystemwatcher_fsevents.cpp @@ -0,0 +1,472 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include <qplatformdefs.h> + +#include "qfilesystemwatcher.h" +#include "qfilesystemwatcher_fsevents_p.h" + +#include <qdebug.h> +#include <qfile.h> +#include <qdatetime.h> +#include <qfileinfo.h> +#include <qvarlengtharray.h> + +#include <mach/mach.h> +#include <sys/types.h> +#include <CoreFoundation/CFRunLoop.h> +#include <CoreFoundation/CFUUID.h> +#include <CoreServices/CoreServices.h> +#include <AvailabilityMacros.h> +#include <private/qcore_mac_p.h> + +QT_BEGIN_NAMESPACE + +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 +// Static operator overloading so for the sake of some convieniece. +// They only live in this compilation unit to avoid polluting Qt in general. +static bool operator==(const struct ::timespec &left, const struct ::timespec &right) +{ + return left.tv_sec == right.tv_sec + && left.tv_nsec == right.tv_nsec; +} + +static bool operator==(const struct ::stat64 &left, const struct ::stat64 &right) +{ + return left.st_dev == right.st_dev + && left.st_mode == right.st_mode + && left.st_size == right.st_size + && left.st_ino == right.st_ino + && left.st_uid == right.st_uid + && left.st_gid == right.st_gid + && left.st_mtimespec == right.st_mtimespec + && left.st_ctimespec == right.st_ctimespec + && left.st_flags == right.st_flags; +} + +static bool operator!=(const struct ::stat64 &left, const struct ::stat64 &right) +{ + return !(operator==(left, right)); +} + + +static void addPathToHash(PathHash &pathHash, const QString &key, const QFileInfo &fileInfo, + const QString &path) +{ + PathInfoList &list = pathHash[key]; + list.push_back(PathInfo(path, + fileInfo.absoluteFilePath().normalized(QString::NormalizationForm_D).toUtf8())); + pathHash.insert(key, list); +} + +static void removePathFromHash(PathHash &pathHash, const QString &key, const QString &path) +{ + PathInfoList &list = pathHash[key]; + // We make the assumption that the list contains unique paths + PathInfoList::iterator End = list.end(); + PathInfoList::iterator it = list.begin(); + while (it != End) { + if (it->originalPath == path) { + list.erase(it); + break; + } + ++it; + } + if (list.isEmpty()) + pathHash.remove(key); +} + +static void stopFSStream(FSEventStreamRef stream) +{ + if (stream) { + FSEventStreamStop(stream); + FSEventStreamInvalidate(stream); + } +} + +static QString createFSStreamPath(const QString &absolutePath) +{ + // The path returned has a trailing slash, so ensure that here. + QString string = absolutePath; + string.reserve(string.size() + 1); + string.append(QLatin1Char('/')); + return string; +} + +static void cleanupFSStream(FSEventStreamRef stream) +{ + if (stream) + FSEventStreamRelease(stream); +} + +const FSEventStreamCreateFlags QtFSEventFlags = (kFSEventStreamCreateFlagUseCFTypes | kFSEventStreamCreateFlagNoDefer /* | kFSEventStreamCreateFlagWatchRoot*/); + +const CFTimeInterval Latency = 0.033; // This will do updates 30 times a second which is probably more than you need. +#endif + +QFSEventsFileSystemWatcherEngine::QFSEventsFileSystemWatcherEngine() + : fsStream(0), pathsToWatch(0), threadsRunLoop(0) +{ +} + +QFSEventsFileSystemWatcherEngine::~QFSEventsFileSystemWatcherEngine() +{ +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 + // I assume that at this point, QFileSystemWatcher has already called stop + // on me, so I don't need to invalidate or stop my stream, simply + // release it. + cleanupFSStream(fsStream); + if (pathsToWatch) + CFRelease(pathsToWatch); +#endif +} + +QFSEventsFileSystemWatcherEngine *QFSEventsFileSystemWatcherEngine::create() +{ + return new QFSEventsFileSystemWatcherEngine(); +} + +QStringList QFSEventsFileSystemWatcherEngine::addPaths(const QStringList &paths, + QStringList *files, + QStringList *directories) +{ +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 + stop(); + QMutexLocker locker(&mutex); + QStringList failedToAdd; + // if we have a running FSStreamEvent, we have to kill it, we'll re-add the stream soon. + FSEventStreamEventId idToCheck; + if (fsStream) { + idToCheck = FSEventStreamGetLatestEventId(fsStream); + cleanupFSStream(fsStream); + } else { + idToCheck = kFSEventStreamEventIdSinceNow; + } + + // Brain-dead approach, but works. FSEvents actually can already read sub-trees, but since it's + // work to figure out if we are doing a double register, we just register it twice as FSEvents + // seems smart enough to only deliver one event. We also duplicate directory entries in here + // (e.g., if you watch five files in the same directory, you get that directory included in the + // array 5 times). This stupidity also makes remove work correctly though. I'll freely admit + // that we could make this a bit smarter. If you do, check the auto-tests, they should catch at + // least a couple of the issues. + QCFType<CFMutableArrayRef> tmpArray = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); + for (int i = 0; i < paths.size(); ++i) { + const QString &path = paths.at(i); + + QFileInfo fileInfo(path); + if (!fileInfo.exists()) { + failedToAdd.append(path); + continue; + } + + if (fileInfo.isDir()) { + if (directories->contains(path)) { + failedToAdd.append(path); + continue; + } else { + directories->append(path); + // Full file path for dirs. + QCFString cfpath(createFSStreamPath(fileInfo.absoluteFilePath())); + addPathToHash(dirPathInfoHash, cfpath, fileInfo, path); + CFArrayAppendValue(tmpArray, cfpath); + } + } else { + if (files->contains(path)) { + failedToAdd.append(path); + continue; + } else { + // Just the absolute path (minus it's filename) for files. + QCFString cfpath(createFSStreamPath(fileInfo.absolutePath())); + files->append(path); + addPathToHash(filePathInfoHash, cfpath, fileInfo, path); + CFArrayAppendValue(tmpArray, cfpath); + } + } + } + if (CFArrayGetCount(tmpArray) > 0) { + if (pathsToWatch) { + CFArrayAppendArray(tmpArray, pathsToWatch, CFRangeMake(0, CFArrayGetCount(pathsToWatch))); + CFRelease(pathsToWatch); + } + pathsToWatch = CFArrayCreateCopy(kCFAllocatorDefault, tmpArray); + } + FSEventStreamContext context = { 0, this, 0, 0, 0 }; + fsStream = FSEventStreamCreate(kCFAllocatorDefault, + QFSEventsFileSystemWatcherEngine::fseventsCallback, + &context, pathsToWatch, + idToCheck, Latency, QtFSEventFlags); + warmUpFSEvents(); + + return failedToAdd; +#else + Q_UNUSED(paths); + Q_UNUSED(files); + Q_UNUSED(directories); + return QStringList(); +#endif +} + +void QFSEventsFileSystemWatcherEngine::warmUpFSEvents() +{ +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 + // This function assumes that the mutex has already been grabbed before calling it. + // It exits with the mutex still locked (Q_ASSERT(mutex.isLocked()) ;-). + start(); + waitCondition.wait(&mutex); +#endif +} + +QStringList QFSEventsFileSystemWatcherEngine::removePaths(const QStringList &paths, + QStringList *files, + QStringList *directories) +{ +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 + stop(); + QMutexLocker locker(&mutex); + // short circuit for smarties that call remove before add and we have nothing. + if (pathsToWatch == 0) + return paths; + QStringList failedToRemove; + // if we have a running FSStreamEvent, we have to stop it, we'll re-add the stream soon. + FSEventStreamEventId idToCheck; + if (fsStream) { + idToCheck = FSEventStreamGetLatestEventId(fsStream); + cleanupFSStream(fsStream); + fsStream = 0; + } else { + idToCheck = kFSEventStreamEventIdSinceNow; + } + + CFIndex itemCount = CFArrayGetCount(pathsToWatch); + QCFType<CFMutableArrayRef> tmpArray = CFArrayCreateMutableCopy(kCFAllocatorDefault, itemCount, + pathsToWatch); + CFRelease(pathsToWatch); + pathsToWatch = 0; + for (int i = 0; i < paths.size(); ++i) { + // Get the itemCount at the beginning to avoid any overruns during the iteration. + itemCount = CFArrayGetCount(tmpArray); + const QString &path = paths.at(i); + QFileInfo fi(path); + QCFString cfpath(createFSStreamPath(fi.absolutePath())); + + CFIndex index = CFArrayGetFirstIndexOfValue(tmpArray, CFRangeMake(0, itemCount), cfpath); + if (index != -1) { + CFArrayRemoveValueAtIndex(tmpArray, index); + files->removeAll(path); + removePathFromHash(filePathInfoHash, cfpath, path); + } else { + // Could be a directory we are watching instead. + QCFString cfdirpath(createFSStreamPath(fi.absoluteFilePath())); + index = CFArrayGetFirstIndexOfValue(tmpArray, CFRangeMake(0, itemCount), cfdirpath); + if (index != -1) { + CFArrayRemoveValueAtIndex(tmpArray, index); + directories->removeAll(path); + removePathFromHash(dirPathInfoHash, cfpath, path); + } else { + failedToRemove.append(path); + } + } + } + itemCount = CFArrayGetCount(tmpArray); + if (itemCount != 0) { + pathsToWatch = CFArrayCreateCopy(kCFAllocatorDefault, tmpArray); + + FSEventStreamContext context = { 0, this, 0, 0, 0 }; + fsStream = FSEventStreamCreate(kCFAllocatorDefault, + QFSEventsFileSystemWatcherEngine::fseventsCallback, + &context, pathsToWatch, idToCheck, Latency, QtFSEventFlags); + warmUpFSEvents(); + } + return failedToRemove; +#else + Q_UNUSED(paths); + Q_UNUSED(files); + Q_UNUSED(directories); + return QStringList(); +#endif +} + +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 +void QFSEventsFileSystemWatcherEngine::updateList(PathInfoList &list, bool directory, bool emitSignals) +{ + PathInfoList::iterator End = list.end(); + PathInfoList::iterator it = list.begin(); + while (it != End) { + struct ::stat64 newInfo; + if (::stat64(it->absolutePath, &newInfo) == 0) { + if (emitSignals) { + if (newInfo != it->savedInfo) { + it->savedInfo = newInfo; + if (directory) + emit directoryChanged(it->originalPath, false); + else + emit fileChanged(it->originalPath, false); + } + } else { + it->savedInfo = newInfo; + } + } else { + if (errno == ENOENT) { + if (emitSignals) { + if (directory) + emit directoryChanged(it->originalPath, true); + else + emit fileChanged(it->originalPath, true); + } + it = list.erase(it); + continue; + } else { + qWarning("%s:%d:QFSEventsFileSystemWatcherEngine: stat error on %s:%s", + __FILE__, __LINE__, qPrintable(it->originalPath), strerror(errno)); + + } + } + ++it; + } +} + +void QFSEventsFileSystemWatcherEngine::updateHash(PathHash &pathHash) +{ + PathHash::iterator HashEnd = pathHash.end(); + PathHash::iterator it = pathHash.begin(); + const bool IsDirectory = (&pathHash == &dirPathInfoHash); + while (it != HashEnd) { + updateList(it.value(), IsDirectory, false); + if (it.value().isEmpty()) + it = pathHash.erase(it); + else + ++it; + } +} +#endif + +void QFSEventsFileSystemWatcherEngine::fseventsCallback(ConstFSEventStreamRef , + void *clientCallBackInfo, size_t numEvents, + void *eventPaths, + const FSEventStreamEventFlags eventFlags[], + const FSEventStreamEventId []) +{ +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 + QFSEventsFileSystemWatcherEngine *watcher = static_cast<QFSEventsFileSystemWatcherEngine *>(clientCallBackInfo); + QMutexLocker locker(&watcher->mutex); + CFArrayRef paths = static_cast<CFArrayRef>(eventPaths); + for (size_t i = 0; i < numEvents; ++i) { + const QString path = QCFString::toQString( + static_cast<CFStringRef>(CFArrayGetValueAtIndex(paths, i))); + const FSEventStreamEventFlags pathFlags = eventFlags[i]; + // There are several flags that may be passed, but we really don't care about them ATM. + // Here they are and why we don't care. + // kFSEventStreamEventFlagHistoryDone--(very unlikely to be gotten, but even then, not much changes). + // kFSEventStreamEventFlagMustScanSubDirs--Likely means the data is very much out of date, we + // aren't coalescing our directories, so again not so much of an issue + // kFSEventStreamEventFlagRootChanged | kFSEventStreamEventFlagMount | kFSEventStreamEventFlagUnmount-- + // These three flags indicate something has changed, but the stat will likely show this, so + // there's not really much to worry about. + // (btw, FSEvents is not the correct way of checking for mounts/unmounts, + // there are real CarbonCore events for that.) + Q_UNUSED(pathFlags); + if (watcher->filePathInfoHash.contains(path)) + watcher->updateList(watcher->filePathInfoHash[path], false, true); + + if (watcher->dirPathInfoHash.contains(path)) + watcher->updateList(watcher->dirPathInfoHash[path], true, true); + } +#else + Q_UNUSED(clientCallBackInfo); + Q_UNUSED(numEvents); + Q_UNUSED(eventPaths); + Q_UNUSED(eventFlags); +#endif +} + +void QFSEventsFileSystemWatcherEngine::stop() +{ +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 + QMutexLocker locker(&mutex); + stopFSStream(fsStream); + if (threadsRunLoop) { + CFRunLoopStop(threadsRunLoop); + waitForStop.wait(&mutex); + } +#endif +} + +void QFSEventsFileSystemWatcherEngine::updateFiles() +{ +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 + QMutexLocker locker(&mutex); + updateHash(filePathInfoHash); + updateHash(dirPathInfoHash); + if (filePathInfoHash.isEmpty() && dirPathInfoHash.isEmpty()) { + // Everything disappeared before we got to start, don't bother. + stop(); + cleanupFSStream(fsStream); + } + waitCondition.wakeAll(); +#endif +} + +void QFSEventsFileSystemWatcherEngine::run() +{ +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 + threadsRunLoop = CFRunLoopGetCurrent(); + FSEventStreamScheduleWithRunLoop(fsStream, threadsRunLoop, kCFRunLoopDefaultMode); + bool startedOK = FSEventStreamStart(fsStream); + // It's recommended by Apple that you only update the files after you've started + // the stream, because otherwise you might miss an update in between starting it. + updateFiles(); +#ifdef QT_NO_DEBUG + Q_UNUSED(startedOK); +#else + Q_ASSERT(startedOK); +#endif + // If for some reason we called stop up above (and invalidated our stream), this call will return + // immediately. + CFRunLoopRun(); + threadsRunLoop = 0; + QMutexLocker locker(&mutex); + waitForStop.wakeAll(); +#endif +} + +QT_END_NAMESPACE diff --git a/src/corelib/io/qfilesystemwatcher_fsevents_p.h b/src/corelib/io/qfilesystemwatcher_fsevents_p.h new file mode 100644 index 0000000..ffc0c68 --- /dev/null +++ b/src/corelib/io/qfilesystemwatcher_fsevents_p.h @@ -0,0 +1,128 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#ifndef FILEWATCHER_FSEVENTS_P_H +#define FILEWATCHER_FSEVENTS_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of the QLibrary class. This header file may change from +// version to version without notice, or even be removed. +// +// We mean it. +// + +#include "qfilesystemwatcher_p.h" + +#include <QtCore/qmutex.h> +#include <QtCore/qwaitcondition.h> +#include <QtCore/qthread.h> +#include <QtCore/QHash> +#include <QtCore/QLinkedList> +#include <private/qcore_mac_p.h> +#include <sys/stat.h> + +typedef struct __FSEventStream *FSEventStreamRef; +typedef const struct __FSEventStream *ConstFSEventStreamRef; +typedef const struct __CFArray *CFArrayRef; +typedef UInt32 FSEventStreamEventFlags; +typedef uint64_t FSEventStreamEventId; + +QT_BEGIN_NAMESPACE + +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 +// Yes, I use a stat64 element here. QFileInfo requires too much knowledge about implementation +// details to be used as a long-standing record. Since I'm going to have to store this information, I can +// do the stat myself too. +struct PathInfo { + PathInfo(const QString &path, const QByteArray &absPath) + : originalPath(path), absolutePath(absPath) {} + QString originalPath; // The path we need to emit + QByteArray absolutePath; // The path we need to stat. + struct ::stat64 savedInfo; // All the info for the path so we can compare it. +}; +typedef QLinkedList<PathInfo> PathInfoList; +typedef QHash<QString, PathInfoList> PathHash; +#endif + +class QFSEventsFileSystemWatcherEngine : public QFileSystemWatcherEngine +{ + Q_OBJECT +public: + ~QFSEventsFileSystemWatcherEngine(); + + static QFSEventsFileSystemWatcherEngine *create(); + + QStringList addPaths(const QStringList &paths, QStringList *files, QStringList *directories); + QStringList removePaths(const QStringList &paths, QStringList *files, QStringList *directories); + + void stop(); + +private: + QFSEventsFileSystemWatcherEngine(); + void warmUpFSEvents(); + void updateFiles(); + + static void fseventsCallback(ConstFSEventStreamRef streamRef, void *clientCallBackInfo, size_t numEvents, + void *eventPaths, const FSEventStreamEventFlags eventFlags[], + const FSEventStreamEventId eventIds[]); + void run(); + FSEventStreamRef fsStream; + CFArrayRef pathsToWatch; + CFRunLoopRef threadsRunLoop; + QMutex mutex; + QWaitCondition waitCondition; + QWaitCondition waitForStop; +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 + PathHash filePathInfoHash; + PathHash dirPathInfoHash; + void updateHash(PathHash &pathHash); + void updateList(PathInfoList &list, bool directory, bool emitSignals); +#endif +}; + +#endif + +QT_END_NAMESPACE diff --git a/src/corelib/io/qfsfileengine_unix.cpp b/src/corelib/io/qfsfileengine_unix.cpp index 47e3db0..c0b6820 100644 --- a/src/corelib/io/qfsfileengine_unix.cpp +++ b/src/corelib/io/qfsfileengine_unix.cpp @@ -413,7 +413,7 @@ bool QFSFileEngine::mkdir(const QString &name, bool createParentDirectories) con if (QT_STAT(chunk, &st) != -1) { if ((st.st_mode & S_IFMT) != S_IFDIR) return false; - } else if (::mkdir(chunk, 0777) != 0) { + } else if (QT_MKDIR(chunk, 0777) != 0) { return false; } } @@ -424,7 +424,7 @@ bool QFSFileEngine::mkdir(const QString &name, bool createParentDirectories) con if (dirName[dirName.length() - 1] == QLatin1Char('/')) dirName = dirName.left(dirName.length() - 1); #endif - return (::mkdir(QFile::encodeName(dirName), 0777) == 0); + return (QT_MKDIR(QFile::encodeName(dirName), 0777) == 0); } bool QFSFileEngine::rmdir(const QString &name, bool recurseParentDirectories) const diff --git a/src/corelib/io/qfsfileengine_win.cpp b/src/corelib/io/qfsfileengine_win.cpp index 53f0144..819034a 100644 --- a/src/corelib/io/qfsfileengine_win.cpp +++ b/src/corelib/io/qfsfileengine_win.cpp @@ -529,8 +529,7 @@ qint64 QFSFileEnginePrivate::nativeSize() const GetFileExInfoStandard, &attribData); if (!ok) { int errorCode = GetLastError(); - if (errorCode != ERROR_INVALID_NAME - && errorCode != ERROR_FILE_NOT_FOUND && errorCode != ERROR_PATH_NOT_FOUND) { + if (errorCode == ERROR_ACCESS_DENIED || errorCode == ERROR_SHARING_VIOLATION) { QByteArray path = nativeFilePath; // path for the FindFirstFile should not end with a trailing slash while (path.endsWith('\\')) @@ -903,8 +902,7 @@ static inline bool isDirPath(const QString &dirPath, bool *existed) DWORD fileAttrib = ::GetFileAttributes((wchar_t*)QFSFileEnginePrivate::longFileName(path).utf16()); if (fileAttrib == INVALID_FILE_ATTRIBUTES) { int errorCode = GetLastError(); - if (errorCode != ERROR_INVALID_NAME - && errorCode != ERROR_FILE_NOT_FOUND && errorCode != ERROR_PATH_NOT_FOUND) { + if (errorCode == ERROR_ACCESS_DENIED || errorCode == ERROR_SHARING_VIOLATION) { // path for the FindFirstFile should not end with a trailing slash while (path.endsWith(QLatin1Char('\\'))) path.chop(1); @@ -1194,8 +1192,7 @@ bool QFSFileEnginePrivate::doStat() const fileAttrib = GetFileAttributes((wchar_t*)QFSFileEnginePrivate::longFileName(fname).utf16()); if (fileAttrib == INVALID_FILE_ATTRIBUTES) { int errorCode = GetLastError(); - if (errorCode != ERROR_INVALID_NAME - && errorCode != ERROR_FILE_NOT_FOUND && errorCode != ERROR_PATH_NOT_FOUND) { + if (errorCode == ERROR_ACCESS_DENIED || errorCode == ERROR_SHARING_VIOLATION) { QString path = QDir::toNativeSeparators(fname); // path for the FindFirstFile should not end with a trailing slash while (path.endsWith(QLatin1Char('\\'))) @@ -1810,8 +1807,7 @@ QDateTime QFSFileEngine::fileTime(FileTime time) const bool ok = ::GetFileAttributesEx((wchar_t*)QFSFileEnginePrivate::longFileName(d->filePath).utf16(), GetFileExInfoStandard, &attribData); if (!ok) { int errorCode = GetLastError(); - if (errorCode != ERROR_INVALID_NAME - && errorCode != ERROR_FILE_NOT_FOUND && errorCode != ERROR_PATH_NOT_FOUND) { + if (errorCode == ERROR_ACCESS_DENIED || errorCode == ERROR_SHARING_VIOLATION) { QString path = QDir::toNativeSeparators(d->filePath); // path for the FindFirstFile should not end with a trailing slash while (path.endsWith(QLatin1Char('\\'))) diff --git a/src/corelib/io/qprocess.cpp b/src/corelib/io/qprocess.cpp index 8d23d35..e75c314 100644 --- a/src/corelib/io/qprocess.cpp +++ b/src/corelib/io/qprocess.cpp @@ -305,7 +305,7 @@ void QProcessPrivate::Channel::clear() writes to its standard output and standard error will be written to the standard output and standard error of the main process. - \sa setReadChannelMode() + \sa setProcessChannelMode() */ /*! @@ -862,7 +862,7 @@ void QProcess::setReadChannelMode(ProcessChannelMode mode) Returns the channel mode of the QProcess standard output and standard error channels. - \sa setReadChannelMode(), ProcessChannelMode, setReadChannel() + \sa setProcessChannelMode(), ProcessChannelMode, setReadChannel() */ QProcess::ProcessChannelMode QProcess::processChannelMode() const { @@ -879,7 +879,7 @@ QProcess::ProcessChannelMode QProcess::processChannelMode() const \snippet doc/src/snippets/code/src_corelib_io_qprocess.cpp 0 - \sa readChannelMode(), ProcessChannelMode, setReadChannel() + \sa processChannelMode(), ProcessChannelMode, setReadChannel() */ void QProcess::setProcessChannelMode(ProcessChannelMode mode) { diff --git a/src/corelib/io/qprocess_unix.cpp b/src/corelib/io/qprocess_unix.cpp index fafce07..168eac2 100644 --- a/src/corelib/io/qprocess_unix.cpp +++ b/src/corelib/io/qprocess_unix.cpp @@ -162,7 +162,17 @@ private: QMap<int, QProcessInfo *> children; }; -Q_GLOBAL_STATIC(QProcessManager, processManager) + +Q_GLOBAL_STATIC(QMutex, processManagerGlobalMutex) + +static QProcessManager *processManager() { + // The constructor of QProcessManager should be called only once + // so we cannot use Q_GLOBAL_STATIC directly for QProcessManager + QMutex *mutex = processManagerGlobalMutex(); + QMutexLocker locker(mutex); + static QProcessManager processManager; + return &processManager; +} QProcessManager::QProcessManager() { @@ -1161,10 +1171,10 @@ bool QProcessPrivate::startDetached(const QString &program, const QStringList &a // To catch the startup of the child int startedPipe[2]; - ::pipe(startedPipe); + qt_safe_pipe(startedPipe); // To communicate the pid of the child int pidPipe[2]; - ::pipe(pidPipe); + qt_safe_pipe(pidPipe); pid_t childPid = qt_fork(); if (childPid == 0) { diff --git a/src/corelib/io/qresource.cpp b/src/corelib/io/qresource.cpp index a70b92f..42c57a4 100644 --- a/src/corelib/io/qresource.cpp +++ b/src/corelib/io/qresource.cpp @@ -62,6 +62,15 @@ //#define DEBUG_RESOURCE_MATCH +#if defined(Q_OS_VXWORKS) +# if defined(m_data) +# undef m_data +# endif +# if defined(m_len) +# undef m_len +# endif +#endif + QT_BEGIN_NAMESPACE @@ -575,7 +584,7 @@ QResource::addSearchPath(const QString &path) Returns the current search path list. This list is consulted when creating a relative resource. - \sa addSearchPath() + \sa QDir::addSearchPath() QDir::setSearchPaths() */ QStringList diff --git a/src/corelib/io/qsettings.cpp b/src/corelib/io/qsettings.cpp index 7de5030..2a483bc 100644 --- a/src/corelib/io/qsettings.cpp +++ b/src/corelib/io/qsettings.cpp @@ -74,6 +74,10 @@ #endif // Q_OS_WIN #endif // QT_NO_QOBJECT +#ifdef Q_OS_VXWORKS +# include <ioLib.h> +#endif + #include <stdlib.h> #ifndef CSIDL_COMMON_APPDATA @@ -167,7 +171,7 @@ static bool isLikelyToBeNfs(int handle) } #elif defined(Q_OS_SOLARIS) || defined(Q_OS_IRIX) || defined(Q_OS_AIX) || defined(Q_OS_HPUX) \ - || defined(Q_OS_OSF) || defined(Q_OS_QNX) || defined(Q_OS_QNX6) || defined(Q_OS_SCO) \ + || defined(Q_OS_OSF) || defined(Q_OS_QNX) || defined(Q_OS_SCO) \ || defined(Q_OS_UNIXWARE) || defined(Q_OS_RELIANT) || defined(Q_OS_NETBSD) QT_BEGIN_INCLUDE_NAMESPACE # include <sys/statvfs.h> diff --git a/src/corelib/io/qtemporaryfile.cpp b/src/corelib/io/qtemporaryfile.cpp index b520bee..e92e729 100644 --- a/src/corelib/io/qtemporaryfile.cpp +++ b/src/corelib/io/qtemporaryfile.cpp @@ -73,7 +73,10 @@ #if defined(Q_OS_WINCE) # include <types.h> -# include "qfunctions_wince.h" +#endif + +#if defined(Q_OS_VXWORKS) +# include <taskLib.h> #endif QT_BEGIN_NAMESPACE @@ -133,6 +136,8 @@ static int _gettemp(char *path, int *doopen, int domkdir, int slen) } #if defined(Q_OS_WIN) && defined(_MSC_VER) && _MSC_VER >= 1400 pid = _getpid(); +#elif defined(Q_OS_VXWORKS) + pid = (pid_t) taskIdCurrent; #else pid = getpid(); #endif @@ -234,7 +239,7 @@ static int _gettemp(char *path, int *doopen, int domkdir, int slen) #ifdef Q_OS_WIN if (QT_MKDIR(path) == 0) #else - if (mkdir(path, 0700) == 0) + if (QT_MKDIR(path, 0700) == 0) #endif return 1; if (errno != EEXIST) diff --git a/src/corelib/kernel/kernel.pri b/src/corelib/kernel/kernel.pri index 8759578..3493784 100644 --- a/src/corelib/kernel/kernel.pri +++ b/src/corelib/kernel/kernel.pri @@ -32,7 +32,8 @@ HEADERS += \ kernel/qsharedmemory_p.h \ kernel/qsystemsemaphore.h \ kernel/qsystemsemaphore_p.h \ - kernel/qfunctions_p.h + kernel/qfunctions_p.h \ + kernel/qguard_p.h SOURCES += \ kernel/qabstracteventdispatcher.cpp \ @@ -54,7 +55,7 @@ SOURCES += \ kernel/qcoreglobaldata.cpp \ kernel/qsharedmemory.cpp \ kernel/qsystemsemaphore.cpp \ - kernel/qpointer.cpp + kernel/qpointer.cpp win32 { SOURCES += \ @@ -112,3 +113,10 @@ unix { contains(QT_CONFIG, clock-gettime):include($$QT_SOURCE_TREE/config.tests/unix/clock-gettime/clock-gettime.pri) } +vxworks { + SOURCES += \ + kernel/qfunctions_vxworks.cpp + HEADERS += \ + kernel/qfunctions_vxworks.h +} + diff --git a/src/corelib/kernel/qabstractitemmodel.cpp b/src/corelib/kernel/qabstractitemmodel.cpp index 1c3371f..5d5d4cc 100644 --- a/src/corelib/kernel/qabstractitemmodel.cpp +++ b/src/corelib/kernel/qabstractitemmodel.cpp @@ -467,6 +467,27 @@ QAbstractItemModel *QAbstractItemModelPrivate::staticEmptyModel() return qEmptyModel(); } +namespace { + struct DefaultRoleNames : public QHash<int, QByteArray> + { + DefaultRoleNames() { + (*this)[Qt::DisplayRole] = "display"; + (*this)[Qt::DecorationRole] = "decoration"; + (*this)[Qt::EditRole] = "edit"; + (*this)[Qt::ToolTipRole] = "toolTip"; + (*this)[Qt::StatusTipRole] = "statusTip"; + (*this)[Qt::WhatsThisRole] = "whatsThis"; + } + }; +} + +Q_GLOBAL_STATIC(DefaultRoleNames, qDefaultRoleNames) + +const QHash<int,QByteArray> &QAbstractItemModelPrivate::defaultRoleNames() +{ + return *qDefaultRoleNames(); +} + /*! \internal return true if \a value contains a numerical type @@ -1863,6 +1884,37 @@ QSize QAbstractItemModel::span(const QModelIndex &) const } /*! + \since 4.6 + + Sets the model's role names to \a roleNames. + + This function is provided to allow mapping of role identifiers to + role property names in Declarative UI. This function must be called + before the model is used. Modifying the role names after the model + has been set may result in undefined behaviour. + + \sa roleNames() +*/ +void QAbstractItemModel::setRoleNames(const QHash<int,QByteArray> &roleNames) +{ + Q_D(QAbstractItemModel); + d->roleNames = roleNames; +} + +/*! + \since 4.6 + + Returns the model's role names. + + \sa setRoleNames() +*/ +const QHash<int,QByteArray> &QAbstractItemModel::roleNames() const +{ + Q_D(const QAbstractItemModel); + return d->roleNames; +} + +/*! Called to let the model know that it should submit whatever it has cached to the permanent storage. Typically used for row editing. @@ -2278,7 +2330,8 @@ void QAbstractItemModel::endRemoveColumns() \note The view to which the model is attached to will be reset as well. When a model is reset it means that any previous data reported from the - model is now invalid and has to be queried for again. + model is now invalid and has to be queried for again. This also means + that the current item and any selected items will become invalid. When a model radically changes its data it can sometimes be easier to just call this function rather than emit dataChanged() to inform other diff --git a/src/corelib/kernel/qabstractitemmodel.h b/src/corelib/kernel/qabstractitemmodel.h index dc7d7bd..a6bbff4 100644 --- a/src/corelib/kernel/qabstractitemmodel.h +++ b/src/corelib/kernel/qabstractitemmodel.h @@ -220,6 +220,8 @@ public: Qt::MatchFlags(Qt::MatchStartsWith|Qt::MatchWrap)) const; virtual QSize span(const QModelIndex &index) const; + const QHash<int,QByteArray> &roleNames() const; + #ifdef Q_NO_USING_KEYWORD inline QObject *parent() const { return QObject::parent(); } #else @@ -282,6 +284,8 @@ protected: void changePersistentIndexList(const QModelIndexList &from, const QModelIndexList &to); QModelIndexList persistentIndexList() const; + void setRoleNames(const QHash<int,QByteArray> &roleNames); + private: Q_DECLARE_PRIVATE(QAbstractItemModel) Q_DISABLE_COPY(QAbstractItemModel) diff --git a/src/corelib/kernel/qabstractitemmodel_p.h b/src/corelib/kernel/qabstractitemmodel_p.h index c047f95..6a29723 100644 --- a/src/corelib/kernel/qabstractitemmodel_p.h +++ b/src/corelib/kernel/qabstractitemmodel_p.h @@ -78,7 +78,7 @@ class Q_CORE_EXPORT QAbstractItemModelPrivate : public QObjectPrivate Q_DECLARE_PUBLIC(QAbstractItemModel) public: - QAbstractItemModelPrivate() : QObjectPrivate(), supportedDragActions(-1) {} + QAbstractItemModelPrivate() : QObjectPrivate(), supportedDragActions(-1), roleNames(defaultRoleNames()) {} void removePersistentIndexData(QPersistentModelIndexData *data); void rowsAboutToBeInserted(const QModelIndex &parent, int first, int last); void rowsInserted(const QModelIndex &parent, int first, int last); @@ -144,6 +144,9 @@ public: } persistent; Qt::DropActions supportedDragActions; + + QHash<int,QByteArray> roleNames; + static const QHash<int,QByteArray> &defaultRoleNames(); }; QT_END_NAMESPACE diff --git a/src/corelib/kernel/qcore_unix.cpp b/src/corelib/kernel/qcore_unix.cpp index c5b0fc7..efa9c6d 100644 --- a/src/corelib/kernel/qcore_unix.cpp +++ b/src/corelib/kernel/qcore_unix.cpp @@ -41,11 +41,18 @@ #include "qcore_unix_p.h" -#include <sys/select.h> -#include <sys/time.h> +#ifndef Q_OS_VXWORKS +# include <sys/select.h> +# include <sys/time.h> +#else +# include <selectLib.h> +#endif + #include <stdlib.h> -#include "qeventdispatcher_unix_p.h" // for the timeval operators +#ifdef Q_OS_MAC +#include <mach/mach_time.h> +#endif #if !defined(QT_NO_CLOCK_MONOTONIC) # if defined(QT_BOOTSTRAPPED) @@ -55,37 +62,72 @@ QT_BEGIN_NAMESPACE -static inline timeval gettime() +bool qt_gettime_is_monotonic() { - timeval tv; -#ifndef QT_NO_CLOCK_MONOTONIC - // use the monotonic clock - static volatile bool monotonicClockDisabled = false; - struct timespec ts; - if (!monotonicClockDisabled) { - if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1) { - monotonicClockDisabled = true; - } else { - tv.tv_sec = ts.tv_sec; - tv.tv_usec = ts.tv_nsec / 1000; - return tv; - } +#if (_POSIX_MONOTONIC_CLOCK-0 > 0) || defined(Q_OS_MAC) + return true; +#else + static int returnValue = 0; + + if (returnValue == 0) { +# if (_POSIX_MONOTONIC_CLOCK-0 < 0) + returnValue = -1; +# elif (_POSIX_MONOTONIC_CLOCK == 0) + // detect if the system support monotonic timers + long x = sysconf(_SC_MONOTONIC_CLOCK); + returnValue = (x >= 200112L) ? 1 : -1; +# endif } + + return returnValue != -1; #endif +} + +timeval qt_gettime() +{ + timeval tv; +#if defined(Q_OS_MAC) + static mach_timebase_info_data_t info = {0,0}; + if (info.denom == 0) + mach_timebase_info(&info); + + uint64_t cpu_time = mach_absolute_time(); + uint64_t nsecs = cpu_time * (info.numer / info.denom); + tv.tv_sec = nsecs / 1000000000ull; + tv.tv_usec = (nsecs / 1000) - (tv.tv_sec * 1000000); + return tv; +#elif (_POSIX_MONOTONIC_CLOCK-0 > 0) + timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); + tv.tv_sec = ts.tv_sec; + tv.tv_usec = ts.tv_nsec / 1000; + return tv; +#else +# if !defined(QT_NO_CLOCK_MONOTONIC) && !defined(QT_BOOTSTRAPPED) + if (qt_gettime_is_monotonic()) { + timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); + tv.tv_sec = ts.tv_sec; + tv.tv_usec = ts.tv_nsec / 1000; + return tv; + } +# endif // use gettimeofday ::gettimeofday(&tv, 0); return tv; +#endif } static inline bool time_update(struct timeval *tv, const struct timeval &start, const struct timeval &timeout) { - struct timeval now = gettime(); - if (now < start) { - // clock reset, give up + if (!qt_gettime_is_monotonic()) { + // we cannot recalculate the timeout without a monotonic clock as the time may have changed return false; } + // clock source is monotonic, so we can recalculate how much timeout is left + struct timeval now = qt_gettime(); *tv = timeout + start - now; return true; } @@ -100,7 +142,7 @@ int qt_safe_select(int nfds, fd_set *fdread, fd_set *fdwrite, fd_set *fdexcept, return ret; } - timeval start = gettime(); + timeval start = qt_gettime(); timeval timeout = *orig_timeout; // loop and recalculate the timeout as needed @@ -119,76 +161,3 @@ int qt_safe_select(int nfds, fd_set *fdread, fd_set *fdwrite, fd_set *fdexcept, } QT_END_NAMESPACE - -#ifdef Q_OS_LINUX -// Don't wait for libc to supply the calls we need -// Make syscalls directly - -# if defined(__GLIBC__) && (__GLIBC__ * 0x100 + __GLIBC_MINOR__) >= 0x0204 -// glibc 2.4 has syscall(...) -# include <sys/syscall.h> -# include <asm/unistd.h> -# else -// no syscall(...) -static inline int syscall(...) { errno = ENOSYS; return -1;} -# endif - -# ifndef __NR_dup3 -# if defined(__i386__) -# define __NR_dup3 330 -# define __NR_pipe2 331 -# elif defined(__x86_64__) -# define __NR_dup3 292 -# define __NR_pipe2 293 -# elif defined(__ia64__) -# define __NR_dup3 1316 -# define __NR_pipe2 1317 -# else -// set the syscalls to absurd numbers so that they'll cause ENOSYS errors -# warning "Please port the pipe2/dup3 code to this platform" -# define __NR_dup3 -1 -# define __NR_pipe2 -1 -# endif -# endif - -# if !defined(__NR_socketcall) && !defined(__NR_accept4) -# if defined(__x86_64__) -# define __NR_accept4 288 -# elif defined(__ia64__) -// not assigned yet to IA-64 -# define __NR_accept4 -1 -# else -// set the syscalls to absurd numbers so that they'll cause ENOSYS errors -# warning "Please port the accept4 code to this platform" -# define __NR_accept4 -1 -# endif -# endif - -QT_BEGIN_NAMESPACE -namespace QtLibcSupplement { - int pipe2(int pipes[], int flags) - { - return syscall(__NR_pipe2, pipes, flags); - } - - int dup3(int oldfd, int newfd, int flags) - { - return syscall(__NR_dup3, oldfd, newfd, flags); - } - - int accept4(int s, sockaddr *addr, QT_SOCKLEN_T *addrlen, int flags) - { -# if defined(__NR_socketcall) - // This platform uses socketcall() instead of raw syscalls - // the SYS_ACCEPT4 number is cross-platform: 18 - return syscall(__NR_socketcall, 18, &s); -# else - return syscall(__NR_accept4, s, addr, addrlen, flags); -# endif - - Q_UNUSED(addr); Q_UNUSED(addrlen); Q_UNUSED(flags); // they're actually used - } -} -QT_END_NAMESPACE -#endif // Q_OS_LINUX - diff --git a/src/corelib/kernel/qcore_unix_p.h b/src/corelib/kernel/qcore_unix_p.h index dd97841..3bdd5ec 100644 --- a/src/corelib/kernel/qcore_unix_p.h +++ b/src/corelib/kernel/qcore_unix_p.h @@ -67,34 +67,22 @@ #include <errno.h> #include <fcntl.h> +#if defined(Q_OS_VXWORKS) +# include <ioLib.h> +#endif + struct sockaddr; -#if defined(Q_OS_LINUX) && defined(__GLIBC__) && (__GLIBC__ * 0x100 + __GLIBC_MINOR__) >= 0x0204 -// Linux supports thread-safe FD_CLOEXEC +#if defined(Q_OS_LINUX) && defined(O_CLOEXEC) # define QT_UNIX_SUPPORTS_THREADSAFE_CLOEXEC 1 - -// add defines for the consts for Linux -# ifndef O_CLOEXEC -# define O_CLOEXEC 02000000 -# endif -# ifndef FD_DUPFD_CLOEXEC -# define F_DUPFD_CLOEXEC 1030 -# endif -# ifndef SOCK_CLOEXEC -# define SOCK_CLOEXEC O_CLOEXEC -# endif -# ifndef SOCK_NONBLOCK -# define SOCK_NONBLOCK O_NONBLOCK -# endif -# ifndef MSG_CMSG_CLOEXEC -# define MSG_CMSG_CLOEXEC 0x40000000 -# endif - QT_BEGIN_NAMESPACE namespace QtLibcSupplement { - Q_CORE_EXPORT int accept4(int, sockaddr *, QT_SOCKLEN_T *, int flags); - Q_CORE_EXPORT int dup3(int oldfd, int newfd, int flags); - Q_CORE_EXPORT int pipe2(int pipes[], int flags); + inline int accept4(int, sockaddr *, QT_SOCKLEN_T *, int) + { errno = ENOSYS; return -1; } + inline int dup3(int, int, int) + { errno = ENOSYS; return -1; } + inline int pipe2(int [], int ) + { errno = ENOSYS; return -1; } } QT_END_NAMESPACE using namespace QT_PREPEND_NAMESPACE(QtLibcSupplement); @@ -110,6 +98,51 @@ using namespace QT_PREPEND_NAMESPACE(QtLibcSupplement); QT_BEGIN_NAMESPACE +// Internal operator functions for timevals +inline timeval &normalizedTimeval(timeval &t) +{ + while (t.tv_usec > 1000000l) { + ++t.tv_sec; + t.tv_usec -= 1000000l; + } + while (t.tv_usec < 0l) { + --t.tv_sec; + t.tv_usec += 1000000l; + } + return t; +} +inline bool operator<(const timeval &t1, const timeval &t2) +{ return t1.tv_sec < t2.tv_sec || (t1.tv_sec == t2.tv_sec && t1.tv_usec < t2.tv_usec); } +inline bool operator==(const timeval &t1, const timeval &t2) +{ return t1.tv_sec == t2.tv_sec && t1.tv_usec == t2.tv_usec; } +inline timeval &operator+=(timeval &t1, const timeval &t2) +{ + t1.tv_sec += t2.tv_sec; + t1.tv_usec += t2.tv_usec; + return normalizedTimeval(t1); +} +inline timeval operator+(const timeval &t1, const timeval &t2) +{ + timeval tmp; + tmp.tv_sec = t1.tv_sec + t2.tv_sec; + tmp.tv_usec = t1.tv_usec + t2.tv_usec; + return normalizedTimeval(tmp); +} +inline timeval operator-(const timeval &t1, const timeval &t2) +{ + timeval tmp; + tmp.tv_sec = t1.tv_sec - (t2.tv_sec - 1); + tmp.tv_usec = t1.tv_usec - (t2.tv_usec + 1000000); + return normalizedTimeval(tmp); +} +inline timeval operator*(const timeval &t1, int mul) +{ + timeval tmp; + tmp.tv_sec = t1.tv_sec * mul; + tmp.tv_usec = t1.tv_usec * mul; + return normalizedTimeval(tmp); +} + // don't call QT_OPEN or ::open // call qt_safe_open static inline int qt_safe_open(const char *pathname, int flags, mode_t mode = 0777) @@ -129,6 +162,7 @@ static inline int qt_safe_open(const char *pathname, int flags, mode_t mode = 07 #undef QT_OPEN #define QT_OPEN qt_safe_open +#ifndef Q_OS_VXWORKS // no POSIX pipes in VxWorks // don't call ::pipe // call qt_safe_pipe static inline int qt_safe_pipe(int pipefd[2], int flags = 0) @@ -140,7 +174,7 @@ static inline int qt_safe_pipe(int pipefd[2], int flags = 0) #endif register int ret; -#if QT_UNIX_SUPPORTS_THREADSAFE_CLOEXEC +#if QT_UNIX_SUPPORTS_THREADSAFE_CLOEXEC && defined(O_CLOEXEC) // use pipe2 flags |= O_CLOEXEC; ret = ::pipe2(pipefd, flags); // pipe2 is Linux-specific and is documented not to return EINTR @@ -164,6 +198,8 @@ static inline int qt_safe_pipe(int pipefd[2], int flags = 0) return 0; } +#endif // Q_OS_VXWORKS + // don't call dup or fcntl(F_DUPFD) static inline int qt_safe_dup(int oldfd, int atleast = 0, int flags = FD_CLOEXEC) { @@ -194,7 +230,7 @@ static inline int qt_safe_dup2(int oldfd, int newfd, int flags = FD_CLOEXEC) Q_ASSERT(flags == FD_CLOEXEC || flags == 0); register int ret; -#if QT_UNIX_SUPPORTS_THREADSAFE_CLOEXEC +#if QT_UNIX_SUPPORTS_THREADSAFE_CLOEXEC && defined(O_CLOEXEC) // use dup3 if (flags & FD_CLOEXEC) { EINTR_LOOP(ret, ::dup3(oldfd, newfd, O_CLOEXEC)); @@ -238,6 +274,8 @@ static inline int qt_safe_close(int fd) #undef QT_CLOSE #define QT_CLOSE qt_safe_close +#ifndef Q_OS_VXWORKS // no processes in VxWorks + static inline int qt_safe_execve(const char *filename, char *const argv[], char *const envp[]) { @@ -267,6 +305,14 @@ static inline pid_t qt_safe_waitpid(pid_t pid, int *status, int options) return ret; } +#endif // Q_OS_VXWORKS + +#if !defined(_POSIX_MONOTONIC_CLOCK) +# define _POSIX_MONOTONIC_CLOCK -1 +#endif + +bool qt_gettime_is_monotonic(); +timeval qt_gettime(); Q_CORE_EXPORT int qt_safe_select(int nfds, fd_set *fdread, fd_set *fdwrite, fd_set *fdexcept, const struct timeval *tv); diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index 706dc54..d0a4943 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -61,6 +61,7 @@ #include <private/qthread_p.h> #include <qlibraryinfo.h> #include <private/qfactoryloader_p.h> +#include <private/qfunctions_p.h> #ifdef Q_OS_UNIX # if !defined(QT_NO_GLIB) @@ -83,6 +84,10 @@ # include <locale.h> #endif +#ifdef Q_OS_VXWORKS +# include <taskLib.h> +#endif + QT_BEGIN_NAMESPACE #if defined(Q_WS_WIN) || defined(Q_WS_MAC) @@ -1821,8 +1826,9 @@ qint64 QCoreApplication::applicationPid() { #if defined(Q_OS_WIN32) || defined(Q_OS_WINCE) return GetCurrentProcessId(); +#elif defined(Q_OS_VXWORKS) + return (pid_t) taskIdCurrent; #else - // UNIX return getpid(); #endif } diff --git a/src/corelib/kernel/qcoreevent.cpp b/src/corelib/kernel/qcoreevent.cpp index a682fad9..ff00c1c 100644 --- a/src/corelib/kernel/qcoreevent.cpp +++ b/src/corelib/kernel/qcoreevent.cpp @@ -269,7 +269,7 @@ QT_BEGIN_NAMESPACE \omitvalue FutureCallOut \omitvalue CocoaRequestModal \omitvalue Signal - \omitvalue WinGesture + \omitvalue NativeGesture */ /*! diff --git a/src/corelib/kernel/qcoreevent.h b/src/corelib/kernel/qcoreevent.h index 1d86f47..d941286 100644 --- a/src/corelib/kernel/qcoreevent.h +++ b/src/corelib/kernel/qcoreevent.h @@ -276,7 +276,7 @@ public: TouchUpdate = 195, TouchEnd = 196, - WinGesture = 197, + NativeGesture = 197, // Internal for platform gesture support // 512 reserved for Qt Jambi's MetaCall event // 513 reserved for Qt Jambi's DeleteOnMainThread event diff --git a/src/corelib/kernel/qeventdispatcher_glib.cpp b/src/corelib/kernel/qeventdispatcher_glib.cpp index 7610631..2bbe560 100644 --- a/src/corelib/kernel/qeventdispatcher_glib.cpp +++ b/src/corelib/kernel/qeventdispatcher_glib.cpp @@ -263,6 +263,7 @@ QEventDispatcherGlibPrivate::QEventDispatcherGlibPrivate(GMainContext *context) (void) new (&timerSource->timerList) QTimerInfoList(); timerSource->processEventsFlags = QEventLoop::AllEvents; g_source_set_can_recurse(&timerSource->source, true); + g_source_set_priority(&timerSource->source, G_PRIORITY_DEFAULT_IDLE); g_source_attach(&timerSource->source, mainContext); } diff --git a/src/corelib/kernel/qeventdispatcher_unix.cpp b/src/corelib/kernel/qeventdispatcher_unix.cpp index 9deb78f..7982d4c 100644 --- a/src/corelib/kernel/qeventdispatcher_unix.cpp +++ b/src/corelib/kernel/qeventdispatcher_unix.cpp @@ -55,12 +55,18 @@ #include <stdio.h> #include <stdlib.h> -#if (_POSIX_MONOTONIC_CLOCK-0 <= 0) || defined(QT_BOOTSTRAPPED) -# include <sys/times.h> +// VxWorks doesn't correctly set the _POSIX_... options +#if defined(Q_OS_VXWORKS) +# if defined(_POSIX_MONOTONIC_CLOCK) && (_POSIX_MONOTONIC_CLOCK <= 0) +# undef _POSIX_MONOTONIC_CLOCK +# define _POSIX_MONOTONIC_CLOCK 1 +# endif +# include <pipeDrv.h> +# include <selectLib.h> #endif -#ifdef Q_OS_MAC -#include <mach/mach_time.h> +#if (_POSIX_MONOTONIC_CLOCK-0 <= 0) || defined(QT_BOOTSTRAPPED) +# include <sys/times.h> #endif QT_BEGIN_NAMESPACE @@ -81,7 +87,7 @@ static void signalHandler(int sig) } -#ifdef Q_OS_INTEGRITY +#if defined(Q_OS_INTEGRITY) || defined(Q_OS_VXWORKS) static void initThreadPipeFD(int fd) { int ret = fcntl(fd, F_SETFD, FD_CLOEXEC); @@ -102,20 +108,47 @@ QEventDispatcherUNIXPrivate::QEventDispatcherUNIXPrivate() { extern Qt::HANDLE qt_application_thread_id; mainThread = (QThread::currentThreadId() == qt_application_thread_id); + bool pipefail = false; // initialize the common parts of the event loop -#ifdef Q_OS_INTEGRITY +#if defined(Q_OS_INTEGRITY) // INTEGRITY doesn't like a "select" on pipes, so use socketpair instead - if (socketpair(AF_INET, SOCK_STREAM, PF_INET, thread_pipe) == -1) + if (socketpair(AF_INET, SOCK_STREAM, PF_INET, thread_pipe) == -1) { perror("QEventDispatcherUNIXPrivate(): Unable to create socket pair"); - - initThreadPipeFD(thread_pipe[0]); - initThreadPipeFD(thread_pipe[1]); + pipefail = true; + } else { + initThreadPipeFD(thread_pipe[0]); + initThreadPipeFD(thread_pipe[1]); + } +#elif defined(Q_OS_VXWORKS) + char name[20]; + qsnprintf(name, sizeof(name), "/pipe/qt_%08x", int(taskIdCurrent)); + + // make sure there is no pipe with this name + pipeDevDelete(name, true); + // create the pipe + if (pipeDevCreate(name, 128 /*maxMsg*/, 1 /*maxLength*/) != OK) { + perror("QEventDispatcherUNIXPrivate(): Unable to create thread pipe device"); + pipefail = true; + } else { + if ((thread_pipe[0] = open(name, O_RDWR, 0)) < 0) { + perror("QEventDispatcherUNIXPrivate(): Unable to create thread pipe"); + pipefail = true; + } else { + initThreadPipeFD(thread_pipe[0]); + thread_pipe[1] = thread_pipe[0]; + } + } #else - if (qt_safe_pipe(thread_pipe, O_NONBLOCK) == -1) + if (qt_safe_pipe(thread_pipe, O_NONBLOCK) == -1) { perror("QEventDispatcherUNIXPrivate(): Unable to create thread pipe"); + pipefail = true; + } #endif + if (pipefail) + qFatal("QEventDispatcherUNIXPrivate(): Can not continue without a thread pipe"); + sn_highest = -1; interrupt = false; @@ -123,9 +156,18 @@ QEventDispatcherUNIXPrivate::QEventDispatcherUNIXPrivate() QEventDispatcherUNIXPrivate::~QEventDispatcherUNIXPrivate() { +#if defined(Q_OS_VXWORKS) + close(thread_pipe[0]); + + char name[20]; + qsnprintf(name, sizeof(name), "/pipe/qt_%08x", int(taskIdCurrent)); + + pipeDevDelete(name, true); +#else // cleanup the common parts of the event loop close(thread_pipe[0]); close(thread_pipe[1]); +#endif // cleanup timers qDeleteAll(timerList); @@ -230,9 +272,15 @@ int QEventDispatcherUNIXPrivate::doSelect(QEventLoop::ProcessEventsFlags flags, // select doesn't immediately return next time int nevents = 0; if (nsel > 0 && FD_ISSET(thread_pipe[0], &sn_vec[0].select_fds)) { +#if defined(Q_OS_VXWORKS) + char c[16]; + ::read(thread_pipe[0], c, sizeof(c)); + ::ioctl(thread_pipe[0], FIOFLUSH, 0); +#else char c[16]; while (::read(thread_pipe[0], c, sizeof(c)) > 0) ; +#endif if (!wakeUps.testAndSetRelease(1, 0)) { // hopefully, this is dead code qWarning("QEventDispatcherUNIX: internal error, wakeUps.testAndSetRelease(1, 0) failed!"); @@ -263,18 +311,10 @@ int QEventDispatcherUNIXPrivate::doSelect(QEventLoop::ProcessEventsFlags flags, QTimerInfoList::QTimerInfoList() { -#if (_POSIX_MONOTONIC_CLOCK-0 <= 0) && !defined(Q_OS_MAC) - useMonotonicTimers = false; - -# if (_POSIX_MONOTONIC_CLOCK == 0) - // detect if the system support monotonic timers - long x = sysconf(_SC_MONOTONIC_CLOCK); - useMonotonicTimers = x != -1; -# endif + currentTime = qt_gettime(); - getTime(currentTime); - - if (!useMonotonicTimers) { +#if (_POSIX_MONOTONIC_CLOCK-0 <= 0) && !defined(Q_OS_MAC) + if (!qt_gettime_is_monotonic()) { // not using monotonic timers, initialize the timeChanged() machinery previousTime = currentTime; @@ -290,12 +330,6 @@ QTimerInfoList::QTimerInfoList() ticksPerSecond = 0; msPerTick = 0; } -#else -# if defined(Q_OS_MAC) - useMonotonicTimers = true; -# endif - // using monotonic timers unconditionally - getTime(currentTime); #endif firstTimerInfo = currentTimerInfo = 0; @@ -303,11 +337,24 @@ QTimerInfoList::QTimerInfoList() timeval QTimerInfoList::updateCurrentTime() { - getTime(currentTime); - return currentTime; + return (currentTime = qt_gettime()); } -#if (_POSIX_MONOTONIC_CLOCK-0 <= 0) || defined(QT_BOOTSTRAPPED) +#if ((_POSIX_MONOTONIC_CLOCK-0 <= 0) && !defined(Q_OS_MAC)) || defined(QT_BOOTSTRAPPED) + +template <> +timeval qAbs(const timeval &t) +{ + timeval tmp = t; + if (tmp.tv_sec < 0) { + tmp.tv_sec = -tmp.tv_sec - 1; + tmp.tv_usec -= 1000000; + } + if (tmp.tv_sec == 0 && tmp.tv_usec < 0) { + tmp.tv_usec = -tmp.tv_usec; + } + return normalizedTimeval(tmp); +} /* Returns true if the real time clock has changed by more than 10% @@ -318,72 +365,35 @@ timeval QTimerInfoList::updateCurrentTime() */ bool QTimerInfoList::timeChanged(timeval *delta) { - tms unused; + struct tms unused; clock_t currentTicks = times(&unused); - int elapsedTicks = currentTicks - previousTicks; + clock_t elapsedTicks = currentTicks - previousTicks; timeval elapsedTime = currentTime - previousTime; - int elapsedMsecTicks = (elapsedTicks * 1000) / ticksPerSecond; - int deltaMsecs = (elapsedTime.tv_sec * 1000 + elapsedTime.tv_usec / 1000) - - elapsedMsecTicks; - if (delta) { - delta->tv_sec = deltaMsecs / 1000; - delta->tv_usec = (deltaMsecs % 1000) * 1000; - } + timeval elapsedTimeTicks; + elapsedTimeTicks.tv_sec = elapsedTicks / ticksPerSecond; + elapsedTimeTicks.tv_usec = (((elapsedTicks * 1000) / ticksPerSecond) % 1000) * 1000; + + timeval dummy; + if (!delta) + delta = &dummy; + *delta = elapsedTime - elapsedTimeTicks; + previousTicks = currentTicks; previousTime = currentTime; // If tick drift is more than 10% off compared to realtime, we assume that the clock has // been set. Of course, we have to allow for the tick granularity as well. - - return (qAbs(deltaMsecs) - msPerTick) * 10 > elapsedMsecTicks; -} - -void QTimerInfoList::getTime(timeval &t) -{ -#if defined(Q_OS_MAC) - { - static mach_timebase_info_data_t info = {0,0}; - if (info.denom == 0) - mach_timebase_info(&info); - - uint64_t cpu_time = mach_absolute_time(); - uint64_t nsecs = cpu_time * (info.numer / info.denom); - t.tv_sec = nsecs * 1e-9; - t.tv_usec = nsecs * 1e-3 - (t.tv_sec * 1e6); - return; - } -#elif !defined(QT_NO_CLOCK_MONOTONIC) && !defined(QT_BOOTSTRAPPED) - if (useMonotonicTimers) { - timespec ts; - clock_gettime(CLOCK_MONOTONIC, &ts); - t.tv_sec = ts.tv_sec; - t.tv_usec = ts.tv_nsec / 1000; - return; - } -#endif - - gettimeofday(&t, 0); - // NTP-related fix - while (t.tv_usec >= 1000000l) { - t.tv_usec -= 1000000l; - ++t.tv_sec; - } - while (t.tv_usec < 0l) { - if (t.tv_sec > 0l) { - t.tv_usec += 1000000l; - --t.tv_sec; - } else { - t.tv_usec = 0l; - break; - } - } + timeval tickGranularity; + tickGranularity.tv_sec = 0; + tickGranularity.tv_usec = msPerTick * 1000; + return elapsedTimeTicks < ((qAbs(*delta) - tickGranularity) * 10); } void QTimerInfoList::repairTimersIfNeeded() { - if (useMonotonicTimers) + if (qt_gettime_is_monotonic()) return; timeval delta; if (timeChanged(&delta)) @@ -392,14 +402,6 @@ void QTimerInfoList::repairTimersIfNeeded() #else // !(_POSIX_MONOTONIC_CLOCK-0 <= 0) && !defined(QT_BOOTSTRAPPED) -void QTimerInfoList::getTime(timeval &t) -{ - timespec ts; - clock_gettime(CLOCK_MONOTONIC, &ts); - t.tv_sec = ts.tv_sec; - t.tv_usec = ts.tv_nsec / 1000; -} - void QTimerInfoList::repairTimersIfNeeded() { } @@ -428,7 +430,7 @@ void QTimerInfoList::timerRepair(const timeval &diff) // repair all timers for (int i = 0; i < size(); ++i) { register QTimerInfo *t = at(i); - t->timeout = t->timeout - diff; + t->timeout = t->timeout + diff; } } @@ -625,25 +627,7 @@ QEventDispatcherUNIX::~QEventDispatcherUNIX() int QEventDispatcherUNIX::select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, timeval *timeout) { - Q_D(QEventDispatcherUNIX); - if (timeout) { - // handle the case where select returns with a timeout, too - // soon. - timeval tvStart = d->timerList.currentTime; - timeval tvCurrent = tvStart; - timeval originalTimeout = *timeout; - - int nsel; - do { - timeval tvRest = originalTimeout + tvStart - tvCurrent; - nsel = ::select(nfds, readfds, writefds, exceptfds, &tvRest); - d->timerList.getTime(tvCurrent); - } while (nsel == 0 && (tvCurrent - tvStart) < originalTimeout); - - return nsel; - } - - return ::select(nfds, readfds, writefds, exceptfds, timeout); + return ::qt_safe_select(nfds, readfds, writefds, exceptfds, timeout); } /*! diff --git a/src/corelib/kernel/qeventdispatcher_unix_p.h b/src/corelib/kernel/qeventdispatcher_unix_p.h index d1f7431..5e016d3 100644 --- a/src/corelib/kernel/qeventdispatcher_unix_p.h +++ b/src/corelib/kernel/qeventdispatcher_unix_p.h @@ -56,54 +56,19 @@ #include "QtCore/qabstracteventdispatcher.h" #include "QtCore/qlist.h" #include "private/qabstracteventdispatcher_p.h" +#include "private/qcore_unix_p.h" #include "private/qpodlist_p.h" -#include <sys/types.h> -#include <sys/time.h> -#if !defined(Q_OS_HPUX) || defined(__ia64) -#include <sys/select.h> +#if defined(Q_OS_VXWORKS) +# include <sys/times.h> +#else +# include <sys/time.h> +# if !defined(Q_OS_HPUX) || defined(__ia64) +# include <sys/select.h> +# endif #endif -#include <unistd.h> QT_BEGIN_NAMESPACE -#if !defined(_POSIX_MONOTONIC_CLOCK) -# define _POSIX_MONOTONIC_CLOCK -1 -#endif - -// Internal operator functions for timevals -inline bool operator<(const timeval &t1, const timeval &t2) -{ return t1.tv_sec < t2.tv_sec || (t1.tv_sec == t2.tv_sec && t1.tv_usec < t2.tv_usec); } -inline bool operator==(const timeval &t1, const timeval &t2) -{ return t1.tv_sec == t2.tv_sec && t1.tv_usec == t2.tv_usec; } -inline timeval &operator+=(timeval &t1, const timeval &t2) -{ - t1.tv_sec += t2.tv_sec; - if ((t1.tv_usec += t2.tv_usec) >= 1000000l) { - ++t1.tv_sec; - t1.tv_usec -= 1000000l; - } - return t1; -} -inline timeval operator+(const timeval &t1, const timeval &t2) -{ - timeval tmp; - tmp.tv_sec = t1.tv_sec + t2.tv_sec; - if ((tmp.tv_usec = t1.tv_usec + t2.tv_usec) >= 1000000l) { - ++tmp.tv_sec; - tmp.tv_usec -= 1000000l; - } - return tmp; -} -inline timeval operator-(const timeval &t1, const timeval &t2) -{ - timeval tmp; - tmp.tv_sec = t1.tv_sec - t2.tv_sec; - if ((tmp.tv_usec = t1.tv_usec - t2.tv_usec) < 0l) { - --tmp.tv_sec; - tmp.tv_usec += 1000000l; - } - return tmp; -} // internal timer info struct QTimerInfo { @@ -116,9 +81,7 @@ struct QTimerInfo { class QTimerInfoList : public QList<QTimerInfo*> { -#if (_POSIX_MONOTONIC_CLOCK-0 <= 0) || defined(QT_BOOTSTRAPPED) - bool useMonotonicTimers; - +#if ((_POSIX_MONOTONIC_CLOCK-0 <= 0) && !defined(Q_OS_MAC)) || defined(QT_BOOTSTRAPPED) timeval previousTime; clock_t previousTicks; int ticksPerSecond; @@ -133,8 +96,6 @@ class QTimerInfoList : public QList<QTimerInfo*> public: QTimerInfoList(); - void getTime(timeval &t); - timeval currentTime; timeval updateCurrentTime(); diff --git a/src/corelib/kernel/qfunctions_p.h b/src/corelib/kernel/qfunctions_p.h index a7f2f9d..ad44a15 100644 --- a/src/corelib/kernel/qfunctions_p.h +++ b/src/corelib/kernel/qfunctions_p.h @@ -57,6 +57,8 @@ #if defined(Q_OS_WINCE) # include "QtCore/qfunctions_wince.h" +#elif defined(Q_OS_VXWORKS) +# include "QtCore/qfunctions_vxworks.h" #endif #ifdef Q_CC_RVCT diff --git a/src/corelib/kernel/qfunctions_vxworks.cpp b/src/corelib/kernel/qfunctions_vxworks.cpp new file mode 100644 index 0000000..def8f4c --- /dev/null +++ b/src/corelib/kernel/qfunctions_vxworks.cpp @@ -0,0 +1,202 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qglobal.h" + +#ifdef Q_OS_VXWORKS + +#include "qplatformdefs.h" +#include "qfunctions_vxworks.h" + +#include <vmLib.h> +#include <selectLib.h> +#include <ioLib.h> + +QT_USE_NAMESPACE + +#ifdef __cplusplus +extern "C" { +#endif + +// no lfind() - used by the TIF image format +void *lfind(const void* key, const void* base, size_t* elements, size_t size, + int (*compare)(const void*, const void*)) +{ + const char* current = (char*) base; + const char* const end = (char*) (current + (*elements) * size); + while (current != end) { + if (compare(current, key) == 0) + return (void*)current; + current += size; + } + return 0; +} + + +// no rand_r(), but rand() +// NOTE: this implementation is wrong for multi threaded applications, +// but there is no way to get it right on VxWorks (in kernel mode) +int rand_r(unsigned int * /*seedp*/) +{ + return rand(); +} + +// no usleep() support +int usleep(unsigned int usec) +{ + div_t dt = div(usec, 1000000); + struct timespec ts = { dt.quot, dt.rem * 1000 }; + + return nanosleep(&ts, 0); +} + + +// gettimeofday() is declared, but is missing from the library +// It IS however defined in the Curtis-Wright X11 libraries, so +// we have to make the symbol 'weak' +#if defined(Q_CC_DIAB) +# pragma weak gettimeofday +#endif +int gettimeofday(struct timeval *tv, void /*struct timezone*/ *) +{ + // the compiler will optimize this and will only use one code path + if (sizeof(struct timeval) == sizeof(struct timespec)) { + int res = clock_gettime(CLOCK_REALTIME, (struct timespec *) tv); + if (!res) + tv->tv_usec /= 1000; + return res; + } else { + struct timespec ts; + + int res = clock_gettime(CLOCK_REALTIME, &ts); + if (!res) { + tv->tv_sec = ts.tv_sec; + tv->tv_usec = ts.tv_nsec / 1000; + } + return res; + } +} + +// neither getpagesize() or sysconf(_SC_PAGESIZE) are available +int getpagesize() +{ + return vmPageSizeGet(); +} + +// symlinks are not supported (lstat is now just a call to stat - see qplatformdefs.h) +int symlink(const char *, const char *) +{ + errno = EIO; + return -1; +} + +ssize_t readlink(const char *, char *, size_t) +{ + errno = EIO; + return -1; +} + +// there's no truncate(), but ftruncate() support... +int truncate(const char *path, off_t length) +{ + int fd = open(path, O_WRONLY, 00777); + if (fd >= 0) { + int res = ftruncate(fd, length); + int en = errno; + close(fd); + errno = en; + return res; + } + // errno is already set by open + return -1; +} + + + +// VxWorks doesn't know about passwd & friends. +// in order to avoid patching the unix fs path everywhere +// we introduce some dummy functions that simulate a single +// 'root' user on the system. + +uid_t getuid() +{ + return 0; +} + +gid_t getgid() +{ + return 0; +} + +uid_t geteuid() +{ + return 0; +} + +struct passwd *getpwuid(uid_t uid) +{ + static struct passwd pwbuf = { "root", 0, 0, 0, 0, 0, 0 }; + + if (uid == 0) { + return &pwbuf; + } else { + errno = ENOENT; + return 0; + } +} + +struct group *getgrgid(gid_t gid) +{ + static struct group grbuf = { "root", 0, 0, 0 }; + + if (gid == 0) { + return &grbuf; + } else { + errno = ENOENT; + return 0; + } +} + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // Q_OS_VXWORKS diff --git a/src/corelib/kernel/qfunctions_vxworks.h b/src/corelib/kernel/qfunctions_vxworks.h new file mode 100644 index 0000000..e31d495 --- /dev/null +++ b/src/corelib/kernel/qfunctions_vxworks.h @@ -0,0 +1,153 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QFUNCTIONS_VXWORKS_H +#define QFUNCTIONS_VXWORKS_H +#ifdef Q_OS_VXWORKS + +#include <unistd.h> +#include <pthread.h> +#include <dirent.h> +#include <signal.h> +#include <string.h> +#include <strings.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/ioctl.h> +#include <sys/times.h> +#include <sys/socket.h> +#include <sys/stat.h> +#include <sys/wait.h> +#include <netinet/in.h> +#ifndef QT_NO_IPV6IFNAME +#include <net/if.h> +#endif + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + +#ifdef QT_BUILD_CORE_LIB +QT_MODULE(Core) +#endif + +QT_END_NAMESPACE +QT_END_HEADER + + +#ifndef RTLD_LOCAL +#define RTLD_LOCAL 0 +#endif + +#ifndef NSIG +#define NSIG _NSIGS +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +// isascii is missing (sometimes!!) +#ifndef isascii +inline int isascii(int c) { return (c & 0x7f); } +#endif + +// no lfind() - used by the TIF image format +void *lfind(const void* key, const void* base, size_t* elements, size_t size, + int (*compare)(const void*, const void*)); + +// no rand_r(), but rand() +// NOTE: this implementation is wrong for multi threaded applications, +// but there is no way to get it right on VxWorks (in kernel mode) +int rand_r(unsigned int * /*seedp*/); + +// no usleep() support +int usleep(unsigned int); + +// gettimeofday() is declared, but is missing from the library. +// It IS however defined in the Curtis-Wright X11 libraries, so +// we have to make the symbol 'weak' +int gettimeofday(struct timeval *tv, void /*struct timezone*/ *) __attribute__((weak)); + +// neither getpagesize() or sysconf(_SC_PAGESIZE) are available +int getpagesize(); + +// symlinks are not supported (lstat is now just a call to stat - see qplatformdefs.h) +int symlink(const char *, const char *); +ssize_t readlink(const char *, char *, size_t); + +// there's no truncate(), but ftruncate() support... +int truncate(const char *path, off_t length); + +// VxWorks doesn't know about passwd & friends. +// in order to avoid patching the unix fs path everywhere +// we introduce some dummy functions that simulate a single +// 'root' user on the system. + +uid_t getuid(); +gid_t getgid(); +uid_t geteuid(); + +struct passwd { + char *pw_name; /* user name */ + char *pw_passwd; /* user password */ + uid_t pw_uid; /* user ID */ + gid_t pw_gid; /* group ID */ + char *pw_gecos; /* real name */ + char *pw_dir; /* home directory */ + char *pw_shell; /* shell program */ +}; + +struct group { + char *gr_name; /* group name */ + char *gr_passwd; /* group password */ + gid_t gr_gid; /* group ID */ + char **gr_mem; /* group members */ +}; + +struct passwd *getpwuid(uid_t uid); +struct group *getgrgid(gid_t gid); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // Q_OS_VXWORKS +#endif // QFUNCTIONS_VXWORKS_H diff --git a/src/corelib/kernel/qguard_p.h b/src/corelib/kernel/qguard_p.h new file mode 100644 index 0000000..6af01ac --- /dev/null +++ b/src/corelib/kernel/qguard_p.h @@ -0,0 +1,157 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGUARD_P_H +#define QGUARD_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of qapplication_*.cpp, qwidget*.cpp and qfiledialog.cpp. This header +// file may change from version to version without notice, or even be removed. +// +// We mean it. +// + +#include "QtCore/qglobal.h" + +QT_BEGIN_NAMESPACE + +class QObject; +template<class T> +class QGuard +{ + QObject *o; + QGuard<QObject> *next; + QGuard<QObject> **prev; + friend void q_guard_addGuard(QGuard<QObject> *); + friend void q_guard_removeGuard(QGuard<QObject> *); + friend class QObjectPrivate; +public: + inline QGuard(); + inline QGuard(T *); + inline QGuard(const QGuard<T> &); + inline virtual ~QGuard(); + + inline QGuard<T> &operator=(const QGuard<T> &o); + inline QGuard<T> &operator=(T *); + + inline bool isNull() const + { return !o; } + + inline T* operator->() const + { return static_cast<T*>(const_cast<QObject*>(o)); } + inline T& operator*() const + { return *static_cast<T*>(const_cast<QObject*>(o)); } + inline operator T*() const + { return static_cast<T*>(const_cast<QObject*>(o)); } + inline T* data() const + { return static_cast<T*>(const_cast<QObject*>(o)); } + +protected: + virtual void objectDestroyed(T *) {} +}; + +QT_END_NAMESPACE + +#include "private/qobject_p.h" + +QT_BEGIN_NAMESPACE + +inline void q_guard_addGuard(QGuard<QObject> *); +inline void q_guard_removeGuard(QGuard<QObject> *); + +template<class T> +QGuard<T>::QGuard() +: o(0), next(0), prev(0) +{ +} + +template<class T> +QGuard<T>::QGuard(T *g) +: o(g), next(0), prev(0) +{ + if (o) q_guard_addGuard(reinterpret_cast<QGuard<QObject> *>(this)); +} + +template<class T> +QGuard<T>::QGuard(const QGuard<T> &g) +: o(g.o), next(0), prev(0) +{ + if (o) q_guard_addGuard(reinterpret_cast<QGuard<QObject> *>(this)); +} + +template<class T> +QGuard<T>::~QGuard() +{ + if (prev) q_guard_removeGuard(reinterpret_cast<QGuard<QObject> *>(this)); + o = 0; +} + +template<class T> +QGuard<T> &QGuard<T>::operator=(const QGuard<T> &g) +{ + if (g.o != o) { + if (prev) + q_guard_removeGuard(reinterpret_cast<QGuard<QObject> *>(this)); + o = g.o; + if (o) q_guard_addGuard(reinterpret_cast<QGuard<QObject> *>(this)); + } + return *this; +} + +template<class T> +inline QGuard<T> &QGuard<T>::operator=(T *g) +{ + if (g != o) { + if (prev) + q_guard_removeGuard(reinterpret_cast<QGuard<QObject> *>(this)); + o = g; + if (o) q_guard_addGuard(reinterpret_cast<QGuard<QObject> *>(this)); + } + return *this; +} + +QT_END_NAMESPACE + +#endif // QGUARD_P_H diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp index 08cecaf..d43c5dd 100644 --- a/src/corelib/kernel/qmetaobject.cpp +++ b/src/corelib/kernel/qmetaobject.cpp @@ -148,7 +148,9 @@ enum PropertyFlags { Resettable = 0x00000004, EnumOrFlag = 0x00000008, StdCppSet = 0x00000100, -// Override = 0x00000200, +// Override = 0x00000200, + Constant = 0x00000400, + Final = 0x00000800, Designable = 0x00001000, ResolveDesignable = 0x00002000, Scriptable = 0x00004000, @@ -179,6 +181,10 @@ enum MethodFlags { MethodScriptable = 0x40 }; +enum MetaObjectFlags { + DynamicMetaObject = 0x01 +}; + struct QMetaObjectPrivate { int revision; @@ -188,6 +194,7 @@ struct QMetaObjectPrivate int propertyCount, propertyData; int enumeratorCount, enumeratorData; int constructorCount, constructorData; + int flags; }; static inline const QMetaObjectPrivate *priv(const uint* data) @@ -277,6 +284,17 @@ int QMetaObject::static_metacall(Call cl, int idx, void **argv) const } /*! + \internal +*/ +int QMetaObject::metacall(QObject *object, Call cl, int idx, void **argv) +{ + if (QMetaObject *mo = object->d_ptr->metaObject) + return static_cast<QAbstractDynamicMetaObject*>(mo)->metaCall(cl, idx, argv); + else + return object->qt_metacall(cl, idx, argv); +} + +/*! \fn const char *QMetaObject::className() const Returns the class name. @@ -696,6 +714,14 @@ int QMetaObject::indexOfProperty(const char *name) const } m = m->d.superdata; } + + if (i == -1 && priv(this->d.data)->revision >= 3 && (priv(this->d.data)->flags & DynamicMetaObject)){ + QAbstractDynamicMetaObject *me = + const_cast<QAbstractDynamicMetaObject *>(static_cast<const QAbstractDynamicMetaObject *>(this)); + + i = me->createProperty(name, 0); + } + return i; } @@ -1326,6 +1352,18 @@ int QMetaMethod::attributes() const } /*! + \since 4.6 + + Returns this method's index. +*/ +int QMetaMethod::methodIndex() const +{ + if (!mobj) + return -1; + return ((handle - priv(mobj->d.data)->methodData) / 5) + mobj->methodOffset(); +} + +/*! Returns the access specification of this method (private, protected, or public). @@ -1525,7 +1563,7 @@ bool QMetaMethod::invoke(QObject *object, // recompute the methodIndex by reversing the arithmetic in QMetaObject::property() int methodIndex = ((handle - priv(mobj->d.data)->methodData) / 5) + mobj->methodOffset(); if (connectionType == Qt::DirectConnection) { - return object->qt_metacall(QMetaObject::InvokeMetaMethod, methodIndex, param) < 0; + return QMetaObject::metacall(object, QMetaObject::InvokeMetaMethod, methodIndex, param) < 0; } else { if (returnValue.data()) { qWarning("QMetaMethod::invoke: Unable to invoke methods with return values in " @@ -2040,6 +2078,18 @@ int QMetaProperty::userType() const } /*! + \since 4.6 + + Returns this property's index. +*/ +int QMetaProperty::propertyIndex() const +{ + if (!mobj) + return -1; + return idx + mobj->propertyOffset(); +} + +/*! Returns true if the property's type is an enumeration value that is used as a flag; otherwise returns false. @@ -2151,9 +2201,8 @@ QVariant QMetaProperty::read(const QObject *object) const value = QVariant(t, (void*)0); argv[0] = value.data(); } - const_cast<QObject*>(object)->qt_metacall(QMetaObject::ReadProperty, - idx + mobj->propertyOffset(), - argv); + QMetaObject::metacall(const_cast<QObject*>(object), QMetaObject::ReadProperty, + idx + mobj->propertyOffset(), argv); if (status != -1) return value; @@ -2224,7 +2273,7 @@ bool QMetaProperty::write(QObject *object, const QVariant &value) const argv[0] = &v; else argv[0] = v.data(); - object->qt_metacall(QMetaObject::WriteProperty, idx + mobj->propertyOffset(), argv); + QMetaObject::metacall(object, QMetaObject::WriteProperty, idx + mobj->propertyOffset(), argv); return status; } @@ -2241,7 +2290,7 @@ bool QMetaProperty::reset(QObject *object) const if (!object || !mobj || !isResettable()) return false; void *argv[] = { 0 }; - object->qt_metacall(QMetaObject::ResetProperty, idx + mobj->propertyOffset(), argv); + QMetaObject::metacall(object, QMetaObject::ResetProperty, idx + mobj->propertyOffset(), argv); return true; } @@ -2355,8 +2404,8 @@ bool QMetaProperty::isDesignable(const QObject *object) const bool b = flags & Designable; if (object) { void *argv[] = { &b }; - const_cast<QObject*>(object)->qt_metacall(QMetaObject::QueryPropertyDesignable, - idx + mobj->propertyOffset(), argv); + QMetaObject::metacall(const_cast<QObject*>(object), QMetaObject::QueryPropertyDesignable, + idx + mobj->propertyOffset(), argv); } return b; @@ -2381,8 +2430,8 @@ bool QMetaProperty::isScriptable(const QObject *object) const bool b = flags & Scriptable; if (object) { void *argv[] = { &b }; - const_cast<QObject*>(object)->qt_metacall(QMetaObject::QueryPropertyScriptable, - idx + mobj->propertyOffset(), argv); + QMetaObject::metacall(const_cast<QObject*>(object), QMetaObject::QueryPropertyScriptable, + idx + mobj->propertyOffset(), argv); } return b; } @@ -2405,8 +2454,8 @@ bool QMetaProperty::isStored(const QObject *object) const bool b = flags & Stored; if (object) { void *argv[] = { &b }; - const_cast<QObject*>(object)->qt_metacall(QMetaObject::QueryPropertyStored, - idx + mobj->propertyOffset(), argv); + QMetaObject::metacall(const_cast<QObject*>(object), QMetaObject::QueryPropertyStored, + idx + mobj->propertyOffset(), argv); } return b; } @@ -2432,13 +2481,41 @@ bool QMetaProperty::isUser(const QObject *object) const bool b = flags & User; if (object) { void *argv[] = { &b }; - const_cast<QObject*>(object)->qt_metacall(QMetaObject::QueryPropertyUser, - idx + mobj->propertyOffset(), argv); + QMetaObject::metacall(const_cast<QObject*>(object), QMetaObject::QueryPropertyUser, + idx + mobj->propertyOffset(), argv); } return b; } /*! + Returns true if the property is constant; otherwise returns false. + + A property is constant if the \c{Q_PROPERTY()}'s \c CONSTANT attribute + is set. +*/ +bool QMetaProperty::isConstant() const +{ + if (!mobj) + return false; + int flags = mobj->d.data[handle + 2]; + return flags & Constant; +} + +/*! + Returns true if the property is final; otherwise returns false. + + A property is final if the \c{Q_PROPERTY()}'s \c FINAL attribute + is set. +*/ +bool QMetaProperty::isFinal() const +{ + if (!mobj) + return false; + int flags = mobj->d.data[handle + 2]; + return flags & Final; +} + +/*! \obsolete Returns true if the property is editable for the given \a object; @@ -2458,8 +2535,8 @@ bool QMetaProperty::isEditable(const QObject *object) const bool b = flags & Editable; if (object) { void *argv[] = { &b }; - const_cast<QObject*>(object)->qt_metacall(QMetaObject::QueryPropertyEditable, - idx + mobj->propertyOffset(), argv); + QMetaObject::metacall(const_cast<QObject*>(object), QMetaObject::QueryPropertyEditable, + idx + mobj->propertyOffset(), argv); } return b; } diff --git a/src/corelib/kernel/qmetaobject.h b/src/corelib/kernel/qmetaobject.h index 000ba6e..419fe06 100644 --- a/src/corelib/kernel/qmetaobject.h +++ b/src/corelib/kernel/qmetaobject.h @@ -69,6 +69,7 @@ public: MethodType methodType() const; enum Attributes { Compatibility = 0x1, Cloned = 0x2, Scriptable = 0x4 }; int attributes() const; + int methodIndex() const; inline const QMetaObject *enclosingMetaObject() const { return mobj; } @@ -178,6 +179,7 @@ public: const char *typeName() const; QVariant::Type type() const; int userType() const; + int propertyIndex() const; bool isReadable() const; bool isWritable() const; @@ -187,6 +189,8 @@ public: bool isStored(const QObject *obj = 0) const; bool isEditable(const QObject *obj = 0) const; bool isUser(const QObject *obj = 0) const; + bool isConstant() const; + bool isFinal() const; bool isFlagType() const; bool isEnumType() const; diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 6503ab0..6520170 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -56,6 +56,7 @@ #include <qvarlengtharray.h> #include <qset.h> #include <qsemaphore.h> +#include <qsharedpointer.h> #include <private/qorderedmutexlocker_p.h> #include <private/qmutexpool_p.h> @@ -122,8 +123,11 @@ extern "C" Q_CORE_EXPORT void qt_removeObject(QObject *) } } +QObjectData::~QObjectData() {} +QDeclarativeData::~QDeclarativeData() {} + QObjectPrivate::QObjectPrivate(int version) - : threadData(0), currentSender(0), currentChildBeingDeleted(0), connectionLists(0), senders(0) + : threadData(0), connectionLists(0), senders(0), currentSender(0), currentChildBeingDeleted(0), declarativeData(0), objectGuards(0) { if (version != QObjectPrivateVersion) qFatal("Cannot mix incompatible Qt libraries"); @@ -139,15 +143,18 @@ QObjectPrivate::QObjectPrivate(int version) receiveChildEvents = true; postedEvents = 0; extraData = 0; - connectedSignals = 0; + for (uint i = 0; i < (sizeof connectedSignals / sizeof connectedSignals[0]); ++i) + connectedSignals[i] = 0; inEventHandler = false; inThreadChangeEvent = false; deleteWatch = 0; + metaObject = 0; hasGuards = false; } QObjectPrivate::~QObjectPrivate() { + delete static_cast<QAbstractDynamicMetaObject*>(metaObject); if (deleteWatch) *deleteWatch = 1; #ifndef QT_NO_USERDATA @@ -425,7 +432,22 @@ void QMetaObject::changeGuard(QObject **ptr, QObject *o) */ void QObjectPrivate::clearGuards(QObject *object) { - if (!QObjectPrivate::get(object)->hasGuards) + QObjectPrivate *priv = QObjectPrivate::get(object); + QGuard<QObject> *guard = priv->objectGuards; + while (guard) { + guard->o = 0; + guard = guard->next; + } + while (priv->objectGuards) { + guard = priv->objectGuards; + guard->prev = 0; + if (guard->next) guard->next->prev = &priv->objectGuards; + priv->objectGuards = guard->next; + guard->next = 0; + guard->objectDestroyed(object); + } + + if (!priv->hasGuards) return; GuardHash *hash = guardHash(); if (hash) { @@ -467,7 +489,7 @@ QMetaCallEvent::~QMetaCallEvent() */ int QMetaCallEvent::placeMetaCall(QObject *object) { - return object->qt_metacall(QMetaObject::InvokeMetaMethod, id_, args_); + return QMetaObject::metacall(object, QMetaObject::InvokeMetaMethod, id_, args_); } /*! @@ -747,7 +769,21 @@ QObject::~QObject() QObjectPrivate::clearGuards(this); } + if (d->sharedRefcount) { + if (d->sharedRefcount->strongref > 0) { + qWarning("QObject: shared QObject was deleted directly. The program is malformed and may crash."); + // but continue deleting, it's too late to stop anyway + } + + // indicate to all QWeakPointers that this QObject has now been deleted + d->sharedRefcount->strongref = 0; + if (!d->sharedRefcount->weakref.deref()) + delete d->sharedRefcount; + } + emit destroyed(this); + if (d->declarativeData) + d->declarativeData->destroyed(this); { QMutexLocker locker(signalSlotLock(this)); @@ -807,9 +843,9 @@ QObject::~QObject() if (senderLists) senderLists->dirty = true; + node = node->next; if (needToUnlock) m->unlock(); - node = node->next; } } @@ -2849,10 +2885,16 @@ bool QMetaObject::connect(const QObject *sender, int signal_index, s->d_func()->addConnection(signal_index, c); - if (signal_index < 0) - sender->d_func()->connectedSignals = ~0u; - else if (signal_index < 32) - sender->d_func()->connectedSignals |= (1 << signal_index); + if (signal_index < 0) { + for (uint i = 0; i < (sizeof sender->d_func()->connectedSignals + / sizeof sender->d_func()->connectedSignals[0] ); ++i) + sender->d_func()->connectedSignals[i] = ~0u; + } else if (signal_index < (int)sizeof sender->d_func()->connectedSignals * 8) { + uint n = (signal_index / (8 * sizeof sender->d_func()->connectedSignals[0])); + sender->d_func()->connectedSignals[n] |= (1 << (signal_index - n * 8 + * sizeof sender->d_func()->connectedSignals[0])); + } + return true; } @@ -3140,10 +3182,10 @@ void QMetaObject::activate(QObject *sender, int from_signal_index, int to_signal } #if defined(QT_NO_EXCEPTIONS) - receiver->qt_metacall(QMetaObject::InvokeMetaMethod, method, argv ? argv : empty_argv); + metacall(receiver, QMetaObject::InvokeMetaMethod, method, argv ? argv : empty_argv); #else try { - receiver->qt_metacall(QMetaObject::InvokeMetaMethod, method, argv ? argv : empty_argv); + metacall(receiver, QMetaObject::InvokeMetaMethod, method, argv ? argv : empty_argv); } catch (...) { locker.relock(); @@ -3192,11 +3234,12 @@ void QMetaObject::activate(QObject *sender, int from_signal_index, int to_signal */ void QMetaObject::activate(QObject *sender, int signal_index, void **argv) { - if (signal_index < 32 + if (signal_index < (int)sizeof(sender->d_func()->connectedSignals) * 8 && !qt_signal_spy_callback_set.signal_begin_callback && !qt_signal_spy_callback_set.signal_end_callback) { - uint signal_mask = 1 << signal_index; - if ((sender->d_func()->connectedSignals & signal_mask) == 0) + uint n = (signal_index / (8 * sizeof sender->d_func()->connectedSignals[0])); + uint m = 1 << (signal_index - n * 8 * sizeof sender->d_func()->connectedSignals[0]); + if ((sender->d_func()->connectedSignals[n] & m) == 0) // nothing connected to these signals, and no spy return; } @@ -3209,11 +3252,12 @@ void QMetaObject::activate(QObject *sender, const QMetaObject *m, int local_sign void **argv) { int signal_index = m->methodOffset() + local_signal_index; - if (signal_index < 32 + if (signal_index < (int)sizeof(sender->d_func()->connectedSignals) * 8 && !qt_signal_spy_callback_set.signal_begin_callback && !qt_signal_spy_callback_set.signal_end_callback) { - uint signal_mask = 1 << signal_index; - if ((sender->d_func()->connectedSignals & signal_mask) == 0) + uint n = (signal_index / (8 * sizeof sender->d_func()->connectedSignals[0])); + uint m = 1 << (signal_index - n * 8 * sizeof sender->d_func()->connectedSignals[0]); + if ((sender->d_func()->connectedSignals[n] & m) == 0) // nothing connected to these signals, and no spy return; } @@ -3225,21 +3269,59 @@ void QMetaObject::activate(QObject *sender, const QMetaObject *m, int local_sign void QMetaObject::activate(QObject *sender, const QMetaObject *m, int from_local_signal_index, int to_local_signal_index, void **argv) { + Q_ASSERT(from_local_signal_index <= to_local_signal_index); int offset = m->methodOffset(); int from_signal_index = offset + from_local_signal_index; int to_signal_index = offset + to_local_signal_index; - if (to_signal_index < 32 + + if (to_signal_index < (int)sizeof(sender->d_func()->connectedSignals) * 8 && !qt_signal_spy_callback_set.signal_begin_callback && !qt_signal_spy_callback_set.signal_end_callback) { - uint signal_mask = (1 << (to_signal_index + 1)) - 1; - signal_mask ^= (1 << from_signal_index) - 1; - if ((sender->d_func()->connectedSignals & signal_mask) == 0) + + uint n = (from_signal_index / (8 * sizeof sender->d_func()->connectedSignals[0])); + uint m = 1 << (from_signal_index - n * 8 * sizeof sender->d_func()->connectedSignals[0]); + uint nt = (to_signal_index / (8 * sizeof sender->d_func()->connectedSignals[0])); + uint mt = 1 << (to_signal_index - n * 8 * sizeof sender->d_func()->connectedSignals[0]); + bool connected = false; + quint32 *connectedSignals = sender->d_func()->connectedSignals; + for (uint i = 0; !connected && i < (sizeof sender->d_func()->connectedSignals + / sizeof sender->d_func()->connectedSignals[0]); ++i) { + uint mask = 0; + if (i > n) + mask = ~0u; + else if (i == n) + mask = ~(m -1); + if (i > nt) + mask = 0; + else if (i == nt) + mask &= (mt << 1) - 1; + connected = connectedSignals[i] & mask; + } + if (!connected) // nothing connected to these signals, and no spy return; } activate(sender, from_signal_index, to_signal_index, argv); } +/*! \internal + + Returns true if the signal with index \a signal_index from object \a sender is connected. + Signals with indices above a certain range are always considered connected (see connectedSignals + in QObjectPrivate). If a signal spy is installed, all signals are considered connected. +*/ +bool QMetaObject::isConnected(QObject *sender, int signal_index) { + if (signal_index < (int)sizeof(sender->d_func()->connectedSignals) * 8 + && !qt_signal_spy_callback_set.signal_begin_callback + && !qt_signal_spy_callback_set.signal_end_callback) { + uint n = (signal_index / (8 * sizeof sender->d_func()->connectedSignals[0])); + uint m = 1 << (signal_index - n * 8 * sizeof sender->d_func()->connectedSignals[0]); + if ((sender->d_func()->connectedSignals[n] & m) == 0) + // nothing connected to these signals, and no spy + return false; + } + return true; +} /***************************************************************************** Properties @@ -3829,23 +3911,17 @@ QDebug operator<<(QDebug dbg, const QObject *o) { Synonym for QList<QObject *>. */ -#ifdef QT_JAMBI_BUILD -class QDPtrAccessor : public QObject { -public: - QObjectData *d() const { return d_ptr; } -}; -#endif - void qDeleteInEventHandler(QObject *o) { #ifdef QT_JAMBI_BUILD if (!o) return; - ((QDPtrAccessor *) o)->d()->inEventHandler = false; + QObjectPrivate::get(o)->inEventHandler = false; #endif delete o; } + QT_END_NAMESPACE #include "moc_qobject.cpp" diff --git a/src/corelib/kernel/qobject.h b/src/corelib/kernel/qobject.h index 1fb216b..9169a90 100644 --- a/src/corelib/kernel/qobject.h +++ b/src/corelib/kernel/qobject.h @@ -109,6 +109,7 @@ public: uint hasGuards : 1; //true iff there is one or more QPointer attached to this object uint unused : 22; int postedEvents; + QMetaObject *metaObject; // assert dynamic }; @@ -379,6 +380,9 @@ inline QList<T> qFindChildren(const QObject *o, const QRegExp &re) #endif // Q_MOC_RUN +template <class T> inline const char * qobject_interface_iid() +{ return 0; } + template <class T> inline T qobject_cast_helper(QObject *object, T) { return static_cast<T>(((T)0)->staticMetaObject.cast(object)); } @@ -395,6 +399,8 @@ inline T qobject_cast(const QObject *object) #ifndef Q_MOC_RUN # define Q_DECLARE_INTERFACE(IFace, IId) \ + template <> inline const char *qobject_interface_iid<IFace *>() \ + { return IId; } \ template <> inline IFace *qobject_cast_helper<IFace *>(QObject *object, IFace *) \ { return (IFace *)(object ? object->qt_metacast(IId) : 0); } \ template <> inline IFace *qobject_cast_helper<IFace *>(const QObject *object, IFace *) \ @@ -458,8 +464,13 @@ inline T qobject_cast(const QObject *object) } +template <class T> inline const char * qobject_interface_iid() +{ return 0; } + #ifndef Q_MOC_RUN # define Q_DECLARE_INTERFACE(IFace, IId) \ + template <> inline const char *qobject_interface_iid<IFace *>() \ + { return IId; } \ template <> inline IFace *qobject_cast<IFace *>(QObject *object) \ { return reinterpret_cast<IFace *>((object ? object->qt_metacast(IId) : 0)); } \ template <> inline IFace *qobject_cast<IFace *>(const QObject *object) \ diff --git a/src/corelib/kernel/qobject_p.h b/src/corelib/kernel/qobject_p.h index 07c397f..5d17bfd 100644 --- a/src/corelib/kernel/qobject_p.h +++ b/src/corelib/kernel/qobject_p.h @@ -60,12 +60,14 @@ #include "QtCore/qvector.h" #include "QtCore/qreadwritelock.h" #include "QtCore/qvariant.h" +#include "private/qguard_p.h" QT_BEGIN_NAMESPACE class QVariant; class QThreadData; class QObjectConnectionListVector; +namespace QtSharedPointer { struct ExternalRefCountData; } /* mirrored in QtTestLib, DON'T CHANGE without prior warning */ struct QSignalSpyCallbackSet @@ -81,56 +83,20 @@ void Q_CORE_EXPORT qt_register_signal_spy_callbacks(const QSignalSpyCallbackSet extern QSignalSpyCallbackSet Q_CORE_EXPORT qt_signal_spy_callback_set; -inline QObjectData::~QObjectData() {} - enum { QObjectPrivateVersion = QT_VERSION }; +class Q_CORE_EXPORT QDeclarativeData +{ +public: + virtual ~QDeclarativeData(); + virtual void destroyed(QObject *) = 0; +}; + class Q_CORE_EXPORT QObjectPrivate : public QObjectData { Q_DECLARE_PUBLIC(QObject) public: - QObjectPrivate(int version = QObjectPrivateVersion); - virtual ~QObjectPrivate(); - -#ifdef QT3_SUPPORT - QList<QObject *> pendingChildInsertedEvents; - void sendPendingChildInsertedEvents(); - void removePendingChildInsertedEvents(QObject *child); -#else - // preserve binary compatibility with code compiled without Qt 3 support - QList<QObject *> unused; -#endif - - // id of the thread that owns the object - QThreadData *threadData; - void moveToThread_helper(); - void setThreadData_helper(QThreadData *currentData, QThreadData *targetData); - void _q_reregisterTimers(void *pointer); - - struct Sender - { - QObject *sender; - int signal; - int ref; - }; - // object currently activating the object - Sender *currentSender; - - QObject *currentChildBeingDeleted; - - bool isSender(const QObject *receiver, const char *signal) const; - QObjectList receiverList(const char *signal) const; - QObjectList senderList() const; - - QList<QPointer<QObject> > eventFilters; - - void setParent_helper(QObject *); - - void deleteChildren(); - - static void clearGuards(QObject *); - struct ExtraData { #ifndef QT_NO_USERDATA @@ -139,12 +105,7 @@ public: QList<QByteArray> propertyNames; QList<QVariant> propertyValues; }; - ExtraData *extraData; - mutable quint32 connectedSignals; - QString objectName; - - // Note: you must hold the signalSlotLock() before accessing the lists below or calling the functions struct Connection { QObject *sender; @@ -159,11 +120,34 @@ public: }; typedef QList<Connection *> ConnectionList; - QObjectConnectionListVector *connectionLists; + struct Sender + { + QObject *sender; + int signal; + int ref; + }; + + + QObjectPrivate(int version = QObjectPrivateVersion); + virtual ~QObjectPrivate(); + void deleteChildren(); + + void setParent_helper(QObject *); + void moveToThread_helper(); + void setThreadData_helper(QThreadData *currentData, QThreadData *targetData); + void _q_reregisterTimers(void *pointer); + + bool isSender(const QObject *receiver, const char *signal) const; + QObjectList receiverList(const char *signal) const; + QObjectList senderList() const; + void addConnection(int signal, Connection *c); void cleanConnectionLists(); - Connection *senders; //linked list; +#ifdef QT3_SUPPORT + void sendPendingChildInsertedEvents(); + void removePendingChildInsertedEvents(QObject *child); +#endif static Sender *setCurrentSender(QObject *receiver, Sender *sender); @@ -172,14 +156,66 @@ public: Sender *previousSender); static int *setDeleteWatch(QObjectPrivate *d, int *newWatch); static void resetDeleteWatch(QObjectPrivate *d, int *oldWatch, int deleteWatch); - - int *deleteWatch; + static void clearGuards(QObject *); static QObjectPrivate *get(QObject *o) { return o->d_func(); } + +public: + QString objectName; + ExtraData *extraData; // extra data set by the user + QThreadData *threadData; // id of the thread that owns the object + + QObjectConnectionListVector *connectionLists; + + Connection *senders; // linked list of connections connected to this object + Sender *currentSender; // object currently activating the object + mutable quint32 connectedSignals[2]; // 64-bit, so doesn't cause padding on 64-bit platforms + +#ifdef QT3_SUPPORT + QList<QObject *> pendingChildInsertedEvents; +#else + // preserve binary compatibility with code compiled without Qt 3 support + // ### why? + QList<QObject *> unused; +#endif + + QList<QPointer<QObject> > eventFilters; + QObject *currentChildBeingDeleted; + + // these objects are all used to indicate that a QObject was deleted + // plus QPointer, which keeps a separate list + QDeclarativeData *declarativeData; + QGuard<QObject> *objectGuards; + QAtomicPointer<QtSharedPointer::ExternalRefCountData> sharedRefcount; + int *deleteWatch; }; +inline void q_guard_addGuard(QGuard<QObject> *g) +{ + QObjectPrivate *p = QObjectPrivate::get(g->o); + if (p->wasDeleted) { + qWarning("QGuard: cannot add guard to deleted object"); + g->o = 0; + return; + } + + g->next = p->objectGuards; + p->objectGuards = g; + g->prev = &p->objectGuards; + if (g->next) + g->next->prev = &g->next; +} + +inline void q_guard_removeGuard(QGuard<QObject> *g) +{ + if (g->next) g->next->prev = g->prev; + *g->prev = g->next; + g->next = 0; + g->prev = 0; +} + Q_DECLARE_TYPEINFO(QObjectPrivate::Connection, Q_MOVABLE_TYPE); Q_DECLARE_TYPEINFO(QObjectPrivate::Sender, Q_MOVABLE_TYPE); @@ -220,6 +256,14 @@ private: void Q_CORE_EXPORT qDeleteInEventHandler(QObject *o); + +struct Q_CORE_EXPORT QAbstractDynamicMetaObject : public QMetaObject +{ + virtual ~QAbstractDynamicMetaObject() {} + virtual int metaCall(QMetaObject::Call, int _id, void **) { return _id; } + virtual int createProperty(const char *, const char *) { return -1; } +}; + QT_END_NAMESPACE #endif // QOBJECT_P_H diff --git a/src/corelib/kernel/qobjectdefs.h b/src/corelib/kernel/qobjectdefs.h index 9187765..1ae46d5 100644 --- a/src/corelib/kernel/qobjectdefs.h +++ b/src/corelib/kernel/qobjectdefs.h @@ -334,6 +334,9 @@ struct Q_CORE_EXPORT QMetaObject static void activate(QObject *sender, int from_signal_index, int to_signal_index, void **argv); static void activate(QObject *sender, const QMetaObject *, int local_signal_index, void **argv); static void activate(QObject *sender, const QMetaObject *, int from_local_signal_index, int to_local_signal_index, void **argv); + + static bool isConnected(QObject *sender, int signal_index); + // internal guarded pointers static void addGuard(QObject **ptr); static void removeGuard(QObject **ptr); @@ -428,6 +431,7 @@ struct Q_CORE_EXPORT QMetaObject }; int static_metacall(Call, int, void **) const; + static int metacall(QObject *, Call, int, void **); #ifdef QT3_SUPPORT QT3_SUPPORT const char *superClassName() const; @@ -439,6 +443,7 @@ struct Q_CORE_EXPORT QMetaObject const uint *data; const void *extradata; } d; + }; struct QMetaObjectExtraData diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp index 2b5ea0a..4166944 100644 --- a/src/corelib/kernel/qvariant.cpp +++ b/src/corelib/kernel/qvariant.cpp @@ -161,6 +161,9 @@ static void construct(QVariant::Private *x, const void *copy) case QMetaType::Float: x->data.f = copy ? *static_cast<const float*>(copy) : 0.0f; break; + case QMetaType::QObjectStar: + x->data.o = copy ? *static_cast<QObject *const*>(copy) : 0; + break; case QVariant::LongLong: x->data.ll = copy ? *static_cast<const qlonglong *>(copy) : Q_INT64_C(0); break; @@ -257,6 +260,7 @@ static void clear(QVariant::Private *d) case QVariant::ULongLong: case QVariant::Double: case QMetaType::Float: + case QMetaType::QObjectStar: break; case QVariant::Invalid: case QVariant::UserType: @@ -326,6 +330,7 @@ static bool isNull(const QVariant::Private *d) case QVariant::Bool: case QVariant::Double: case QMetaType::Float: + case QMetaType::QObjectStar: break; } return d->is_null; @@ -419,6 +424,8 @@ static bool compare(const QVariant::Private *a, const QVariant::Private *b) return a->data.d == b->data.d; case QMetaType::Float: return a->data.f == b->data.f; + case QMetaType::QObjectStar: + return a->data.o == b->data.o; case QVariant::Date: return *v_cast<QDate>(a) == *v_cast<QDate>(b); case QVariant::Time: @@ -1048,6 +1055,9 @@ static void streamDebug(QDebug dbg, const QVariant &v) case QMetaType::Float: dbg.nospace() << qVariantValue<float>(v); break; + case QMetaType::QObjectStar: + dbg.nospace() << qVariantValue<QObject *>(v); + break; case QVariant::Double: dbg.nospace() << v.toDouble(); break; @@ -1361,7 +1371,7 @@ void QVariant::create(int type, const void *copy) QVariant::~QVariant() { - if (d.type > Char && d.type != QMetaType::Float && (!d.is_shared || !d.data.shared->ref.deref())) + if (d.type > Char && d.type != QMetaType::Float && d.type != QMetaType::QObjectStar && (!d.is_shared || !d.data.shared->ref.deref())) handler->clear(&d); } @@ -1377,7 +1387,7 @@ QVariant::QVariant(const QVariant &p) { if (d.is_shared) { d.data.shared->ref.ref(); - } else if (p.d.type > Char && p.d.type != QMetaType::Float) { + } else if (p.d.type > Char && p.d.type != QMetaType::Float && p.d.type != QMetaType::QObjectStar) { handler->construct(&d, p.constData()); d.is_null = p.d.is_null; } @@ -1733,7 +1743,7 @@ QVariant& QVariant::operator=(const QVariant &variant) if (variant.d.is_shared) { variant.d.data.shared->ref.ref(); d = variant.d; - } else if (variant.d.type > Char && variant.d.type != QMetaType::Float) { + } else if (variant.d.type > Char && variant.d.type != QMetaType::Float && variant.d.type != QMetaType::QObjectStar) { d.type = variant.d.type; handler->construct(&d, variant.constData()); d.is_null = variant.d.is_null; diff --git a/src/corelib/kernel/qvariant.h b/src/corelib/kernel/qvariant.h index a68939d..4489e95 100644 --- a/src/corelib/kernel/qvariant.h +++ b/src/corelib/kernel/qvariant.h @@ -358,6 +358,7 @@ class Q_CORE_EXPORT QVariant float f; qlonglong ll; qulonglong ull; + QObject *o; void *ptr; PrivateShared *shared; } data; diff --git a/src/corelib/plugin/qlibrary.cpp b/src/corelib/plugin/qlibrary.cpp index 8f364ba..309bfb8 100644 --- a/src/corelib/plugin/qlibrary.cpp +++ b/src/corelib/plugin/qlibrary.cpp @@ -667,12 +667,15 @@ bool QLibraryPrivate::isPlugin(QSettings *settings) #endif } + // Qt 4.5 compatibility: stl doesn't affect binary compatibility + key.replace(" no-stl", ""); + +#ifndef QT_NO_SETTINGS QStringList queried; queried << QString::number(qt_version,16) << QString::number((int)debug) << QLatin1String(key) << lastModified; -#ifndef QT_NO_SETTINGS settings->setValue(regkey, queried); #endif } diff --git a/src/corelib/plugin/qlibrary_unix.cpp b/src/corelib/plugin/qlibrary_unix.cpp index 6b9e1ad..cc70589 100644 --- a/src/corelib/plugin/qlibrary_unix.cpp +++ b/src/corelib/plugin/qlibrary_unix.cpp @@ -58,7 +58,7 @@ QT_BEGIN_NAMESPACE -#if !defined(QT_HPUX_LD) +#if !defined(QT_HPUX_LD) && !defined(Q_OS_VXWORKS) QT_BEGIN_INCLUDE_NAMESPACE #include <dlfcn.h> QT_END_INCLUDE_NAMESPACE @@ -66,7 +66,9 @@ QT_END_INCLUDE_NAMESPACE static QString qdlerror() { -#if !defined(QT_HPUX_LD) +#if defined(Q_OS_VXWORKS) + const char *err = "VxWorks does not support dynamic libraries."; +#elif !defined(QT_HPUX_LD) const char *err = dlerror(); #else const char *err = strerror(errno); @@ -76,6 +78,8 @@ static QString qdlerror() bool QLibraryPrivate::load_sys() { + QString attempt; +#if !defined(Q_OS_VXWORKS) QFileInfo fi(fileName); QString path = fi.path(); QString name = fi.fileName(); @@ -163,7 +167,6 @@ bool QLibraryPrivate::load_sys() } #endif #endif // QT_HPUX_LD - QString attempt; bool retry = true; for(int prefix = 0; retry && !pHnd && prefix < prefixes.size(); prefix++) { for(int suffix = 0; retry && !pHnd && suffix < suffixes.size(); suffix++) { @@ -204,7 +207,8 @@ bool QLibraryPrivate::load_sys() attempt = str; } } -# endif +#endif +#endif // Q_OS_VXWORKS if (!pHnd) { errorString = QLibrary::tr("Cannot load library %1: %2").arg(fileName).arg(qdlerror()); } @@ -217,14 +221,16 @@ bool QLibraryPrivate::load_sys() bool QLibraryPrivate::unload_sys() { -#if defined(QT_HPUX_LD) +#if !defined(Q_OS_VXWORKS) +# if defined(QT_HPUX_LD) if (shl_unload((shl_t)pHnd)) { -#else +# else if (dlclose(pHnd)) { -#endif +# endif errorString = QLibrary::tr("Cannot unload library %1: %2").arg(fileName).arg(qdlerror()); return false; } +#endif errorString.clear(); return true; } @@ -249,6 +255,8 @@ void* QLibraryPrivate::resolve_sys(const char* symbol) void* address = 0; if (shl_findsym((shl_t*)&pHnd, symbol, TYPE_UNDEFINED, &address) < 0) address = 0; +#elif defined(Q_OS_VXWORKS) + void *address = 0; #else void* address = dlsym(pHnd, symbol); #endif diff --git a/src/corelib/statemachine/qabstracttransition.cpp b/src/corelib/statemachine/qabstracttransition.cpp index 0004d3e..3248dcf 100644 --- a/src/corelib/statemachine/qabstracttransition.cpp +++ b/src/corelib/statemachine/qabstracttransition.cpp @@ -153,34 +153,12 @@ QAbstractTransition::QAbstractTransition(QState *sourceState) } /*! - Constructs a new QAbstractTransition object with the given \a targets and \a - sourceState. -*/ -QAbstractTransition::QAbstractTransition(const QList<QAbstractState*> &targets, - QState *sourceState) - : QObject(*new QAbstractTransitionPrivate, sourceState) -{ - setTargetStates(targets); -} - -/*! - \internal -*/ -QAbstractTransition::QAbstractTransition(QAbstractTransitionPrivate &dd, - QState *parent) - : QObject(dd, parent) -{ -} - -/*! \internal */ QAbstractTransition::QAbstractTransition(QAbstractTransitionPrivate &dd, - const QList<QAbstractState*> &targets, QState *parent) : QObject(dd, parent) { - setTargetStates(targets); } /*! diff --git a/src/corelib/statemachine/qabstracttransition.h b/src/corelib/statemachine/qabstracttransition.h index 9ba1f11..8ff3a6e 100644 --- a/src/corelib/statemachine/qabstracttransition.h +++ b/src/corelib/statemachine/qabstracttransition.h @@ -72,7 +72,6 @@ class Q_CORE_EXPORT QAbstractTransition : public QObject Q_PROPERTY(QList<QAbstractState*> targetStates READ targetStates WRITE setTargetStates) public: QAbstractTransition(QState *sourceState = 0); - QAbstractTransition(const QList<QAbstractState*> &targets, QState *sourceState = 0); virtual ~QAbstractTransition(); QState *sourceState() const; @@ -104,8 +103,6 @@ protected: protected: QAbstractTransition(QAbstractTransitionPrivate &dd, QState *parent); - QAbstractTransition(QAbstractTransitionPrivate &dd, - const QList<QAbstractState*> &targets, QState *parent); private: Q_DISABLE_COPY(QAbstractTransition) diff --git a/src/corelib/statemachine/qeventtransition.cpp b/src/corelib/statemachine/qeventtransition.cpp index 3933981..813c960 100644 --- a/src/corelib/statemachine/qeventtransition.cpp +++ b/src/corelib/statemachine/qeventtransition.cpp @@ -153,22 +153,6 @@ QEventTransition::QEventTransition(QObject *object, QEvent::Type type, } /*! - Constructs a new QEventTransition object associated with events of the given - \a type for the given \a object. The transition has the given \a targets and - \a sourceState. -*/ -QEventTransition::QEventTransition(QObject *object, QEvent::Type type, - const QList<QAbstractState*> &targets, - QState *sourceState) - : QAbstractTransition(*new QEventTransitionPrivate, targets, sourceState) -{ - Q_D(QEventTransition); - d->registered = false; - d->object = object; - d->eventType = type; -} - -/*! \internal */ QEventTransition::QEventTransition(QEventTransitionPrivate &dd, QState *parent) @@ -190,20 +174,6 @@ QEventTransition::QEventTransition(QEventTransitionPrivate &dd, QObject *object, } /*! - \internal -*/ -QEventTransition::QEventTransition(QEventTransitionPrivate &dd, QObject *object, - QEvent::Type type, const QList<QAbstractState*> &targets, - QState *parent) - : QAbstractTransition(dd, targets, parent) -{ - Q_D(QEventTransition); - d->registered = false; - d->object = object; - d->eventType = type; -} - -/*! Destroys this QObject event transition. */ QEventTransition::~QEventTransition() diff --git a/src/corelib/statemachine/qeventtransition.h b/src/corelib/statemachine/qeventtransition.h index b05ffef..0ebca19 100644 --- a/src/corelib/statemachine/qeventtransition.h +++ b/src/corelib/statemachine/qeventtransition.h @@ -62,8 +62,6 @@ class Q_CORE_EXPORT QEventTransition : public QAbstractTransition public: QEventTransition(QState *sourceState = 0); QEventTransition(QObject *object, QEvent::Type type, QState *sourceState = 0); - QEventTransition(QObject *object, QEvent::Type type, - const QList<QAbstractState*> &targets, QState *sourceState = 0); ~QEventTransition(); QObject *eventObject() const; @@ -82,9 +80,6 @@ protected: QEventTransition(QEventTransitionPrivate &dd, QState *parent); QEventTransition(QEventTransitionPrivate &dd, QObject *object, QEvent::Type type, QState *parent); - QEventTransition(QEventTransitionPrivate &dd, QObject *object, - QEvent::Type type, const QList<QAbstractState*> &targets, - QState *parent); private: Q_DISABLE_COPY(QEventTransition) diff --git a/src/corelib/statemachine/qsignalevent.h b/src/corelib/statemachine/qsignalevent.h index c09c5a3..b7ca61f 100644 --- a/src/corelib/statemachine/qsignalevent.h +++ b/src/corelib/statemachine/qsignalevent.h @@ -58,16 +58,16 @@ QT_MODULE(Core) class Q_CORE_EXPORT QSignalEvent : public QEvent { public: - QSignalEvent(const QObject *sender, int signalIndex, + QSignalEvent(QObject *sender, int signalIndex, const QList<QVariant> &arguments); ~QSignalEvent(); - inline const QObject *sender() const { return m_sender; } + inline QObject *sender() const { return m_sender; } inline int signalIndex() const { return m_signalIndex; } inline QList<QVariant> arguments() const { return m_arguments; } private: - const QObject *m_sender; + QObject *m_sender; int m_signalIndex; QList<QVariant> m_arguments; }; diff --git a/src/corelib/statemachine/qsignaltransition.cpp b/src/corelib/statemachine/qsignaltransition.cpp index 389e513..7814699 100644 --- a/src/corelib/statemachine/qsignaltransition.cpp +++ b/src/corelib/statemachine/qsignaltransition.cpp @@ -159,21 +159,6 @@ QSignalTransition::QSignalTransition(QObject *sender, const char *signal, } /*! - Constructs a new signal transition associated with the given \a signal of - the given \a sender. The transition has the given \a targets and \a - sourceState. -*/ -QSignalTransition::QSignalTransition(QObject *sender, const char *signal, - const QList<QAbstractState*> &targets, - QState *sourceState) - : QAbstractTransition(*new QSignalTransitionPrivate, targets, sourceState) -{ - Q_D(QSignalTransition); - d->sender = sender; - d->signal = signal; -} - -/*! Destroys this signal transition. */ QSignalTransition::~QSignalTransition() diff --git a/src/corelib/statemachine/qsignaltransition.h b/src/corelib/statemachine/qsignaltransition.h index 69060ae..415751e 100644 --- a/src/corelib/statemachine/qsignaltransition.h +++ b/src/corelib/statemachine/qsignaltransition.h @@ -62,9 +62,6 @@ public: QSignalTransition(QState *sourceState = 0); QSignalTransition(QObject *sender, const char *signal, QState *sourceState = 0); - QSignalTransition(QObject *sender, const char *signal, - const QList<QAbstractState*> &targets, - QState *sourceState = 0); ~QSignalTransition(); QObject *senderObject() const; diff --git a/src/corelib/statemachine/qstate.cpp b/src/corelib/statemachine/qstate.cpp index f74edc3..09d0be0 100644 --- a/src/corelib/statemachine/qstate.cpp +++ b/src/corelib/statemachine/qstate.cpp @@ -215,6 +215,8 @@ QList<QAbstractTransition*> QStatePrivate::transitions() const return result; } +#ifndef QT_NO_PROPERTIES + /*! Instructs this state to set the property with the given \a name of the given \a object to the given \a value when the state is entered. @@ -239,6 +241,8 @@ void QState::assignProperty(QObject *object, const char *name, d->propertyAssignments.append(QPropertyAssignment(object, name, value)); } +#endif // QT_NO_PROPERTIES + /*! Returns this state's error state. @@ -335,7 +339,8 @@ QSignalTransition *QState::addTransition(QObject *sender, const char *signal, return 0; } } - QSignalTransition *trans = new QSignalTransition(sender, signal, QList<QAbstractState*>() << target); + QSignalTransition *trans = new QSignalTransition(sender, signal); + trans->setTargetState(target); addTransition(trans); return trans; } @@ -347,7 +352,8 @@ class UnconditionalTransition : public QAbstractTransition { public: UnconditionalTransition(QAbstractState *target) - : QAbstractTransition(QList<QAbstractState*>() << target) {} + : QAbstractTransition() + { setTargetState(target); } protected: void onTransition(QEvent *) {} bool eventTest(QEvent *) { return true; } diff --git a/src/corelib/statemachine/qstate.h b/src/corelib/statemachine/qstate.h index 41d32be..ce88b25 100644 --- a/src/corelib/statemachine/qstate.h +++ b/src/corelib/statemachine/qstate.h @@ -87,8 +87,10 @@ public: ChildMode childMode() const; void setChildMode(ChildMode mode); +#ifndef QT_NO_PROPERTIES void assignProperty(QObject *object, const char *name, const QVariant &value); +#endif Q_SIGNALS: void finished(); diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp index 5402b04..9cb1d4d 100644 --- a/src/corelib/statemachine/qstatemachine.cpp +++ b/src/corelib/statemachine/qstatemachine.cpp @@ -205,6 +205,7 @@ This is QStateMachinePrivate::QStateMachinePrivate() { state = NotRunning; + _startState = 0; processing = false; processingScheduled = false; stop = false; @@ -395,7 +396,9 @@ void QStateMachinePrivate::microstep(QEvent *event, const QList<QAbstractTransit #endif executeTransitionContent(event, enabledTransitions); QList<QAbstractState*> enteredStates = enterStates(event, enabledTransitions); +#ifndef QT_NO_PROPERTIES applyProperties(enabledTransitions, exitedStates, enteredStates); +#endif #ifdef QSTATEMACHINE_DEBUG qDebug() << q_func() << ": configuration after entering states:" << configuration; qDebug() << q_func() << ": end microstep"; @@ -666,6 +669,8 @@ void QStateMachinePrivate::addStatesToEnter(QAbstractState *s, QState *root, } } +#ifndef QT_NO_PROPERTIES + void QStateMachinePrivate::applyProperties(const QList<QAbstractTransition*> &transitionList, const QList<QAbstractState*> &exitedStates, const QList<QAbstractState*> &enteredStates) @@ -853,6 +858,8 @@ void QStateMachinePrivate::applyProperties(const QList<QAbstractTransition*> &tr } } +#endif // QT_NO_PROPERTIES + bool QStateMachinePrivate::isFinal(const QAbstractState *s) { return qobject_cast<const QFinalState*>(s) != 0; @@ -932,6 +939,8 @@ bool QStateMachinePrivate::isInFinalState(QAbstractState* s) const return false; } +#ifndef QT_NO_PROPERTIES + void QStateMachinePrivate::registerRestorable(QObject *object, const QByteArray &propertyName) { RestorableId id(object, propertyName); @@ -976,6 +985,8 @@ void QStateMachinePrivate::unregisterRestorable(QObject *object, const QByteArra registeredRestorables.remove(id); } +#endif // QT_NO_PROPERTIES + QAbstractState *QStateMachinePrivate::findErrorState(QAbstractState *context) { // Find error state recursively in parent hierarchy if not set explicitly for context state @@ -1088,12 +1099,14 @@ void QStateMachinePrivate::_q_animationFinished() resetAnimationEndValues.remove(anim); } +#ifndef QT_NO_PROPERTIES // Set the final property value. QPropertyAssignment assn = propertyForAnimation.take(anim); Q_ASSERT(assn.object != 0); assn.object->setProperty(assn.propertyName, assn.value); if (!assn.explicitlySet) unregisterRestorable(assn.object, assn.propertyName); +#endif QAbstractState *state = stateForAnimation.take(anim); Q_ASSERT(state != 0); @@ -1126,7 +1139,8 @@ class InitialTransition : public QAbstractTransition { public: InitialTransition(QAbstractState *target) - : QAbstractTransition(QList<QAbstractState*>() << target) {} + : QAbstractTransition() + { setTargetState(target); } protected: virtual bool eventTest(QEvent *) { return true; } virtual void onTransition(QEvent *) {} @@ -1134,6 +1148,20 @@ protected: } // namespace +QState *QStateMachinePrivate::startState() +{ + Q_Q(QStateMachine); + if (_startState == 0) + _startState = new StartState(q); + return _startState; +} + +void QStateMachinePrivate::removeStartState() +{ + delete _startState; + _startState = 0; +} + void QStateMachinePrivate::_q_start() { Q_Q(QStateMachine); @@ -1153,17 +1181,27 @@ void QStateMachinePrivate::_q_start() processingScheduled = true; // we call _q_process() below emit q->started(); - StartState *start = new StartState(rootState()); - QAbstractTransition *initialTransition = new InitialTransition(initial); - start->addTransition(initialTransition); - QList<QAbstractTransition*> transitions; - transitions.append(initialTransition); + QState *start = startState(); + Q_ASSERT(start != 0); + + QList<QAbstractTransition*> transitions = QStatePrivate::get(start)->transitions(); + + // If a transition has already been added, then we skip this step, as the + // initial transition in that case has been overridden. + if (transitions.isEmpty()) { + QAbstractTransition *initialTransition = new InitialTransition(initial); + start->addTransition(initialTransition); + transitions.append(initialTransition); + } + QEvent nullEvent(QEvent::None); executeTransitionContent(&nullEvent, transitions); QList<QAbstractState*> enteredStates = enterStates(&nullEvent, transitions); +#ifndef QT_NO_PROPERTIES applyProperties(transitions, QList<QAbstractState*>() << start, enteredStates); - delete start; +#endif + removeStartState(); #ifdef QSTATEMACHINE_DEBUG qDebug() << q << ": initial configuration:" << configuration; @@ -1263,6 +1301,68 @@ void QStateMachinePrivate::scheduleProcess() QMetaObject::invokeMethod(q_func(), "_q_process", Qt::QueuedConnection); } +namespace { + +class GoToStateTransition : public QAbstractTransition +{ +public: + GoToStateTransition(QAbstractState *target) + : QAbstractTransition() + { setTargetState(target); } +protected: + void onTransition(QEvent *) { deleteLater(); } + bool eventTest(QEvent *) { return true; } +}; + +} // namespace + +/*! + \internal + + Causes this state machine to unconditionally transition to the given + \a targetState. + + Provides a backdoor for using the state machine "imperatively"; i.e. rather + than defining explicit transitions, you drive the machine's execution by + calling this function. It breaks the whole integrity of the + transition-driven model, but is provided for pragmatic reasons. +*/ +void QStateMachinePrivate::goToState(QAbstractState *targetState) +{ + if (!targetState) { + qWarning("QStateMachine::goToState(): cannot go to null state"); + return; + } + + if (configuration.contains(targetState)) + return; + + QState *sourceState = 0; + if (state == Running) { + QSet<QAbstractState*>::const_iterator it; + for (it = configuration.constBegin(); it != configuration.constEnd(); ++it) { + sourceState = qobject_cast<QState*>(*it); + if (sourceState != 0) + break; + } + } else { + sourceState = startState(); + } + + Q_ASSERT(sourceState != 0); + // Reuse previous GoToStateTransition in case of several calls to + // goToState() in a row. + GoToStateTransition *trans = qFindChild<GoToStateTransition*>(sourceState); + if (!trans) { + trans = new GoToStateTransition(targetState); + sourceState->addTransition(trans); + } else { + trans->setTargetState(targetState); + } + + scheduleProcess(); +} + void QStateMachinePrivate::registerTransitions(QAbstractState *state) { QState *group = qobject_cast<QState*>(state); @@ -1432,7 +1532,7 @@ void QStateMachinePrivate::unregisterEventTransition(QEventTransition *transitio } #endif -void QStateMachinePrivate::handleTransitionSignal(const QObject *sender, int signalIndex, +void QStateMachinePrivate::handleTransitionSignal(QObject *sender, int signalIndex, void **argv) { Q_ASSERT(connections[sender].at(signalIndex) != 0); @@ -2012,7 +2112,7 @@ QSignalEventGenerator::QSignalEventGenerator(QStateMachine *parent) Constructs a new QSignalEvent object with the given \a sender, \a signalIndex and \a arguments. */ -QSignalEvent::QSignalEvent(const QObject *sender, int signalIndex, +QSignalEvent::QSignalEvent(QObject *sender, int signalIndex, const QList<QVariant> &arguments) : QEvent(QEvent::Signal), m_sender(sender), m_signalIndex(signalIndex), m_arguments(arguments) diff --git a/src/corelib/statemachine/qstatemachine_p.h b/src/corelib/statemachine/qstatemachine_p.h index 21e405d..f0f74d6 100644 --- a/src/corelib/statemachine/qstatemachine_p.h +++ b/src/corelib/statemachine/qstatemachine_p.h @@ -79,7 +79,7 @@ class QAbstractAnimation; #endif class QStateMachine; -class QStateMachinePrivate : public QStatePrivate +class Q_CORE_EXPORT QStateMachinePrivate : public QStatePrivate { Q_DECLARE_PUBLIC(QStateMachine) public: @@ -116,6 +116,9 @@ public: QState *rootState() const; + QState *startState(); + void removeStartState(); + void microstep(QEvent *event, const QList<QAbstractTransition*> &transitionList); bool isPreempted(const QAbstractState *s, const QSet<QAbstractTransition*> &transitions) const; QSet<QAbstractTransition*> selectTransitions(QEvent *event) const; @@ -138,6 +141,8 @@ public: static bool isDescendantOf(const QAbstractState *s, const QAbstractState *other); static QList<QState*> properAncestors(const QAbstractState *s, const QState *upperBound); + void goToState(QAbstractState *targetState); + void registerTransitions(QAbstractState *state); void registerSignalTransition(QSignalTransition *transition); void unregisterSignalTransition(QSignalTransition *transition); @@ -147,10 +152,11 @@ public: #endif void unregisterTransition(QAbstractTransition *transition); void unregisterAllTransitions(); - void handleTransitionSignal(const QObject *sender, int signalIndex, + void handleTransitionSignal(QObject *sender, int signalIndex, void **args); void scheduleProcess(); +#ifndef QT_NO_PROPERTIES typedef QPair<QObject *, QByteArray> RestorableId; QHash<RestorableId, QVariant> registeredRestorables; void registerRestorable(QObject *object, const QByteArray &propertyName); @@ -158,8 +164,10 @@ public: bool hasRestorable(QObject *object, const QByteArray &propertyName) const; QVariant restorableValue(QObject *object, const QByteArray &propertyName) const; QList<QPropertyAssignment> restorablesToPropertyList(const QHash<RestorableId, QVariant> &restorables) const; +#endif State state; + QState *_startState; bool processing; bool processingScheduled; bool stop; @@ -206,7 +214,7 @@ public: f_cloneEvent cloneEvent; }; - static Q_CORE_EXPORT const Handler *handler; + static const Handler *handler; }; QT_END_NAMESPACE diff --git a/src/corelib/thread/qmutex_unix.cpp b/src/corelib/thread/qmutex_unix.cpp index 43ba668..02c7c6f 100644 --- a/src/corelib/thread/qmutex_unix.cpp +++ b/src/corelib/thread/qmutex_unix.cpp @@ -49,6 +49,10 @@ #include <errno.h> +#if defined(Q_OS_VXWORKS) && defined(wakeup) +#undef wakeup +#endif + QT_BEGIN_NAMESPACE static void report_error(int code, const char *where, const char *what) diff --git a/src/corelib/thread/qthread_unix.cpp b/src/corelib/thread/qthread_unix.cpp index 19b5104..efe37ad 100644 --- a/src/corelib/thread/qthread_unix.cpp +++ b/src/corelib/thread/qthread_unix.cpp @@ -61,6 +61,13 @@ #ifdef Q_OS_BSD4 #include <sys/sysctl.h> #endif +#ifdef Q_OS_VXWORKS +# if (_WRS_VXWORKS_MAJOR > 6) || ((_WRS_VXWORKS_MAJOR == 6) && (_WRS_VXWORKS_MINOR >= 6)) +# include <vxCpuLib.h> +# include <cpuset.h> +# define QT_VXWORKS_HAS_CPUSET +# endif +#endif #if defined(Q_OS_MAC) # ifdef qDebug @@ -85,6 +92,13 @@ static pthread_key_t current_thread_data_key; static void destroy_current_thread_data(void *p) { +#if defined(Q_OS_VXWORKS) + // Calling setspecific(..., 0) sets the value to 0 for ALL threads. + // The 'set to 1' workaround adds a bit of an overhead though, + // since this function is called twice now. + if (p == (void *)1) + return; +#endif // POSIX says the value in our key is set to zero before calling // this destructor function, so we need to set it back to the // right value... @@ -93,7 +107,12 @@ static void destroy_current_thread_data(void *p) // ... but we must reset it to zero before returning so we aren't // called again (POSIX allows implementations to call destructor // functions repeatedly until all values are zero) - pthread_setspecific(current_thread_data_key, 0); + pthread_setspecific(current_thread_data_key, +#if defined(Q_OS_VXWORKS) + (void *)1); +#else + 0); +#endif } static void create_current_thread_data_key() @@ -267,7 +286,25 @@ int QThread::idealThreadCount() // IRIX cores = (int)sysconf(_SC_NPROC_ONLN); #elif defined(Q_OS_INTEGRITY) - // ### TODO - how to get the amound of CPUs on INTEGRITY? + // as of aug 2008 Integrity only supports one single core CPU + cores = 1; +#elif defined(Q_OS_VXWORKS) + // VxWorks +# if defined(QT_VXWORKS_HAS_CPUSET) + cpuset_t cpus = vxCpuEnabledGet(); + cores = 0; + + // 128 cores should be enough for everyone ;) + for (int i = 0; i < 128 && !CPUSET_ISZERO(cpus); ++i) { + if (CPUSET_ISSET(cpus, i)) { + CPUSET_CLR(cpus, i); + cores++; + } + } +# else + // as of aug 2008 VxWorks < 6.6 only supports one single core CPU + cores = 1; +# endif #else // the rest: Linux, Solaris, AIX, Tru64 cores = (int)sysconf(_SC_NPROCESSORS_ONLN); diff --git a/src/corelib/tools/qbytearraymatcher.h b/src/corelib/tools/qbytearraymatcher.h index 697b6ff..4bad24c 100644 --- a/src/corelib/tools/qbytearraymatcher.h +++ b/src/corelib/tools/qbytearraymatcher.h @@ -81,13 +81,14 @@ private: // explicitely allow anonymous unions for RVCT to prevent compiler warnings #pragma anon_unions #endif + struct Data { + uchar q_skiptable[256]; + const uchar *p; + int l; + }; union { uint dummy[256]; - struct { - uchar q_skiptable[256]; - const uchar *p; - int l; - } p; + Data p; }; }; diff --git a/src/corelib/tools/qbytedata_p.h b/src/corelib/tools/qbytedata_p.h index cc10ea2..f3724f6 100644 --- a/src/corelib/tools/qbytedata_p.h +++ b/src/corelib/tools/qbytedata_p.h @@ -42,8 +42,18 @@ #ifndef QBYTEDATA_H #define QBYTEDATA_H -#include <qbytearray.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 <qbytearray.h> QT_BEGIN_NAMESPACE diff --git a/src/corelib/tools/qcontiguouscache.h b/src/corelib/tools/qcontiguouscache.h index 0020d22..7221925 100644 --- a/src/corelib/tools/qcontiguouscache.h +++ b/src/corelib/tools/qcontiguouscache.h @@ -44,6 +44,7 @@ #include <QtCore/qatomic.h> #include <limits.h> +#include <new> QT_BEGIN_HEADER @@ -76,6 +77,12 @@ struct QContiguousCacheTypedData int start; int offset; uint sharable : 1; + // uint unused : 31; + + // total is 24 bytes (HP-UX aCC: 40 bytes) + // the next entry is already aligned to 8 bytes + // there will be an 8 byte gap here if T requires 16-byte alignment + // (such as long double on 64-bit platforms, __int128, __float128) T array[1]; }; diff --git a/src/corelib/tools/qlocale.cpp b/src/corelib/tools/qlocale.cpp index 85e49c7..8608fe4 100644 --- a/src/corelib/tools/qlocale.cpp +++ b/src/corelib/tools/qlocale.cpp @@ -2640,6 +2640,8 @@ static QString timeZone() # else return QString::fromLocal8Bit(_tzname[1]); # endif +#elif defined(Q_OS_VXWORKS) + return QString(); #else tzset(); return QString::fromLocal8Bit(tzname[1]); @@ -4938,6 +4940,9 @@ static inline void Storeinc(ULong *&a, const ULong &b, const ULong &c) #define Bletch 0x10 #define Bndry_mask 0xfffff #define Bndry_mask1 0xfffff +#if defined(LSB) && defined(Q_OS_VXWORKS) +#undef LSB +#endif #define LSB 1 #define Sign_bit 0x80000000 #define Log2P 1 diff --git a/src/corelib/tools/qregexp.cpp b/src/corelib/tools/qregexp.cpp index 3527308..c1d48ec 100644 --- a/src/corelib/tools/qregexp.cpp +++ b/src/corelib/tools/qregexp.cpp @@ -688,6 +688,10 @@ int qFindString(const QChar *haystack, int haystackLen, int from, {tools/regexp}{Regular Expression Example} */ +#if defined(Q_OS_VXWORKS) && defined(EOS) +# undef EOS +#endif + const int NumBadChars = 64; #define BadChar(ch) ((ch).unicode() % NumBadChars) diff --git a/src/corelib/tools/qshareddata.cpp b/src/corelib/tools/qshareddata.cpp index 3cd37a7..6cd220c 100644 --- a/src/corelib/tools/qshareddata.cpp +++ b/src/corelib/tools/qshareddata.cpp @@ -51,7 +51,7 @@ QT_BEGIN_NAMESPACE QSharedData is designed to be used with QSharedDataPointer or QExplicitlySharedDataPointer to implement custom \l{implicitly - shared} or \l {explicitly shared} classes. QSharedData provides + shared} or explicitly shared classes. QSharedData provides \l{thread-safe} reference counting. See QSharedDataPointer and QExplicitlySharedDataPointer for details. diff --git a/src/corelib/tools/qsharedpointer.cpp b/src/corelib/tools/qsharedpointer.cpp index 85085c5..f18dee8 100644 --- a/src/corelib/tools/qsharedpointer.cpp +++ b/src/corelib/tools/qsharedpointer.cpp @@ -128,7 +128,7 @@ To access the pointer that QWeakPointer is tracking, you must first create a QSharedPointer object and verify if the pointer - is null or not. + is null or not. See QWeakPointer::toStrongRef() for more information. \sa QSharedPointer */ @@ -210,6 +210,8 @@ If \tt T is a derived type of the template parameter of this class, QSharedPointer will perform an automatic cast. Otherwise, you will get a compiler error. + + \sa QWeakPointer::toStrongRef() */ /*! @@ -362,6 +364,8 @@ Returns a weak reference object that shares the pointer referenced by this object. + + \sa QWeakPointer::QWeakPointer() */ /*! @@ -478,10 +482,78 @@ */ /*! + \fn T *QWeakPointer::data() const + \since 4.6 + + Returns the value of the pointer being tracked by this QWeakPointer, + \b without ensuring that it cannot get deleted. To have that guarantee, + use toStrongRef(), which returns a QSharedPointer object. If this + function can determine that the pointer has already been deleted, it + returns 0. + + It is ok to obtain the value of the pointer and using that value itself, + like for example in debugging statements: + + \code + qDebug("Tracking %p", weakref.data()); + \endcode + + However, dereferencing the pointer is only allowed if you can guarantee + by external means that the pointer does not get deleted. For example, + if you can be certain that no other thread can delete it, nor the + functions that you may call. + + If that is the case, then the following code is valid: + + \code + // this pointer cannot be used in another thread + // so other threads cannot delete it + QWeakPointer<int> weakref = obtainReference(); + + Object *obj = weakref.data(); + if (obj) { + // if the pointer wasn't deleted yet, we know it can't get + // deleted by our own code here nor the functions we call + otherFunction(obj); + } + \endcode + + Use this function with care. + + \sa isNull(), toStrongRef() +*/ + +/*! \fn QSharedPointer<T> QWeakPointer::toStrongRef() const Promotes this weak reference to a strong one and returns a - QSharedPointer object holding that reference. + QSharedPointer object holding that reference. When promoting to + QSharedPointer, this function verifies if the object has been deleted + already or not. If it hasn't, this function increases the reference + count to the shared object, thus ensuring that it will not get + deleted. + + Since this function can fail to obtain a valid strong reference to the + shared object, you should always verify if the conversion succeeded, + by calling QSharedPointer::isNull() on the returned object. + + For example, the following code promotes a QWeakPointer that was held + to a strong reference and, if it succeeded, it prints the value of the + integer that was held: + + \code + QWeakPointer<int> weakref; + + // ... + + QSharedPointer<int> strong = weakref.toStrongRef(); + if (strong) + qDebug() << "The value is:" << *strong; + else + qDebug() << "The value has already been deleted"; + \endcode + + \sa QSharedPointer::QSharedPointer() */ /*! @@ -792,6 +864,56 @@ #include <qset.h> #include <qmutex.h> +#if !defined(QT_NO_QOBJECT) +#include "../kernel/qobject_p.h" + +/*! + \internal + This function is called for a just-created QObject \a obj, to enable + the use of QSharedPointer and QWeakPointer. + + When QSharedPointer is active in a QObject, the object must not be deleted + directly: the lifetime is managed by the QSharedPointer object. In that case, + the deleteLater() and parent-child relationship in QObject only decrease + the strong reference count, instead of deleting the object. +*/ +void QtSharedPointer::ExternalRefCountData::setQObjectShared(const QObject *obj, bool) +{ + Q_ASSERT(obj); + QObjectPrivate *d = QObjectPrivate::get(const_cast<QObject *>(obj)); + + if (d->sharedRefcount) + qFatal("QSharedPointer: pointer %p already has reference counting", obj); + d->sharedRefcount = this; + + // QObject decreases the refcount too, so increase it up + weakref.ref(); +} + +QtSharedPointer::ExternalRefCountData *QtSharedPointer::ExternalRefCountData::getAndRef(const QObject *obj) +{ + Q_ASSERT(obj); + QObjectPrivate *d = QObjectPrivate::get(const_cast<QObject *>(obj)); + ExternalRefCountData *that = d->sharedRefcount; + if (that) { + that->weakref.ref(); + return that; + } + + // we can create the refcount data because it doesn't exist + ExternalRefCountData *x = new ExternalRefCountData(Qt::Uninitialized); + x->strongref = -1; + x->weakref = 2; // the QWeakPointer that called us plus the QObject itself + if (!d->sharedRefcount.testAndSetRelease(0, x)) { + delete x; + d->sharedRefcount->weakref.ref(); + } + return d->sharedRefcount; +} +#endif + + + #if !defined(QT_NO_MEMBER_TEMPLATES) //# define QT_SHARED_POINTER_BACKTRACE_SUPPORT @@ -803,29 +925,19 @@ # endif # endif -# if !defined(BACKTRACE_SUPPORTED) -// Dummy implementation of the functions. -// Using QHashDummyValue also means that the QHash below is actually a QSet -typedef QT_PREPEND_NAMESPACE(QHashDummyValue) Backtrace; - -static inline Backtrace saveBacktrace() { return Backtrace(); } -static inline void printBacktrace(Backtrace) { } - -# else +# if defined(BACKTRACE_SUPPORTED) # include <sys/types.h> # include <execinfo.h> # include <stdio.h> # include <unistd.h> # include <sys/wait.h> -typedef QT_PREPEND_NAMESPACE(QByteArray) Backtrace; - -static inline Backtrace saveBacktrace() __attribute__((always_inline)); -static inline Backtrace saveBacktrace() +static inline QByteArray saveBacktrace() __attribute__((always_inline)); +static inline QByteArray saveBacktrace() { static const int maxFrames = 32; - Backtrace stacktrace; + QByteArray stacktrace; stacktrace.resize(sizeof(void*) * maxFrames); int stack_size = backtrace((void**)stacktrace.data(), maxFrames); stacktrace.resize(sizeof(void*) * stack_size); @@ -833,7 +945,7 @@ static inline Backtrace saveBacktrace() return stacktrace; } -static void printBacktrace(Backtrace stacktrace) +static void printBacktrace(QByteArray stacktrace) { void *const *stack = (void *const *)stacktrace.constData(); int stack_size = stacktrace.size() / sizeof(void*); @@ -884,11 +996,19 @@ static void printBacktrace(Backtrace stacktrace) namespace { QT_USE_NAMESPACE + struct Data { + const volatile void *pointer; +# ifdef BACKTRACE_SUPPORTED + QByteArray backtrace; +# endif + }; + class KnownPointers { public: QMutex mutex; - QHash<void *, Backtrace> values; + QHash<const void *, Data> dPointers; + QHash<const volatile void *, const void *> dataPointers; }; } @@ -896,38 +1016,122 @@ Q_GLOBAL_STATIC(KnownPointers, knownPointers) QT_BEGIN_NAMESPACE +namespace QtSharedPointer { + Q_CORE_EXPORT void internalSafetyCheckAdd(const volatile void *); + Q_CORE_EXPORT void internalSafetyCheckRemove(const volatile void *); + Q_AUTOTEST_EXPORT void internalSafetyCheckCleanCheck(); +} + +/*! + \internal +*/ +void QtSharedPointer::internalSafetyCheckAdd(const volatile void *) +{ + // Qt 4.5 compatibility + // this function is broken by design, so it was replaced with internalSafetyCheckAdd2 + // + // it's broken because we tracked the pointers added and + // removed from QSharedPointer, converted to void*. + // That is, this is supposed to track the "top-of-object" pointer in + // case of multiple inheritance. + // + // However, it doesn't work well in some compilers: + // if you create an object with a class of type A and the last reference + // is dropped of type B, then the value passed to internalSafetyCheckRemove could + // be different than was added. That would leave dangling addresses. + // + // So instead, we track the pointer by the d-pointer instead. +} + +/*! + \internal +*/ +void QtSharedPointer::internalSafetyCheckRemove(const volatile void *) +{ + // Qt 4.5 compatibility + // see comments above +} + /*! \internal */ -void QtSharedPointer::internalSafetyCheckAdd(const volatile void *ptr) +void QtSharedPointer::internalSafetyCheckAdd2(const void *d_ptr, const volatile void *ptr) { + // see comments above for the rationale for this function KnownPointers *const kp = knownPointers(); if (!kp) return; // end-game: the application is being destroyed already QMutexLocker lock(&kp->mutex); - void *actual = const_cast<void*>(ptr); - if (kp->values.contains(actual)) { - printBacktrace(knownPointers()->values.value(actual)); - qFatal("QSharedPointerData: internal self-check failed: pointer %p was already tracked " - "by another QSharedPointerData object", actual); + Q_ASSERT(!kp->dPointers.contains(d_ptr)); + + //qDebug("Adding d=%p value=%p", d_ptr, ptr); + + const void *other_d_ptr = kp->dataPointers.value(ptr, 0); + if (other_d_ptr) { +# ifdef BACKTRACE_SUPPORTED + printBacktrace(knownPointers()->dPointers.value(other_d_ptr).backtrace); +# endif + qFatal("QSharedPointer: internal self-check failed: pointer %p was already tracked " + "by another QSharedPointer object %p", ptr, other_d_ptr); } - kp->values.insert(actual, saveBacktrace()); + Data data; + data.pointer = ptr; +# ifdef BACKTRACE_SUPPORTED + data.backtrace = saveBacktrace(); +# endif + + kp->dPointers.insert(d_ptr, data); + kp->dataPointers.insert(ptr, d_ptr); + Q_ASSERT(kp->dPointers.size() == kp->dataPointers.size()); } /*! \internal */ -void QtSharedPointer::internalSafetyCheckRemove(const volatile void *ptr) +void QtSharedPointer::internalSafetyCheckRemove2(const void *d_ptr) { KnownPointers *const kp = knownPointers(); if (!kp) return; // end-game: the application is being destroyed already QMutexLocker lock(&kp->mutex); - void *actual = const_cast<void*>(ptr); - kp->values.remove(actual); + + QHash<const void *, Data>::iterator it = kp->dPointers.find(d_ptr); + if (it == kp->dPointers.end()) { + qFatal("QSharedPointer: internal self-check inconsistency: pointer %p was not tracked. " + "To use QT_SHAREDPOINTER_TRACK_POINTERS, you have to enable it throughout " + "in your code.", d_ptr); + } + + QHash<const volatile void *, const void *>::iterator it2 = kp->dataPointers.find(it->pointer); + Q_ASSERT(it2 != kp->dataPointers.end()); + + //qDebug("Removing d=%p value=%p", d_ptr, it->pointer); + + // remove entries + kp->dataPointers.erase(it2); + kp->dPointers.erase(it); + Q_ASSERT(kp->dPointers.size() == kp->dataPointers.size()); +} + +/*! + \internal + Called by the QSharedPointer autotest +*/ +void QtSharedPointer::internalSafetyCheckCleanCheck() +{ +# ifdef QT_BUILD_INTERNAL + KnownPointers *const kp = knownPointers(); + Q_ASSERT_X(kp, "internalSafetyCheckSelfCheck()", "Called after global statics deletion!"); + + if (kp->dPointers.size() != kp->dataPointers.size()) + qFatal("Internal consistency error: the number of pointers is not equal!"); + + if (!kp->dPointers.isEmpty()) + qFatal("Pointer cleaning failed: %d entries remaining", kp->dPointers.size()); +# endif } QT_END_NAMESPACE diff --git a/src/corelib/tools/qsharedpointer.h b/src/corelib/tools/qsharedpointer.h index abd83ad..2f86ce7 100644 --- a/src/corelib/tools/qsharedpointer.h +++ b/src/corelib/tools/qsharedpointer.h @@ -115,6 +115,7 @@ public: QWeakPointer<T> operator=(const QWeakPointer<T> &other); QWeakPointer<T> operator=(const QSharedPointer<T> &other); + T *data() const; void clear(); QSharedPointer<T> toStrongRef() const; diff --git a/src/corelib/tools/qsharedpointer_impl.h b/src/corelib/tools/qsharedpointer_impl.h index 739a949..8a34362 100644 --- a/src/corelib/tools/qsharedpointer_impl.h +++ b/src/corelib/tools/qsharedpointer_impl.h @@ -48,6 +48,7 @@ #pragma qt_sync_stop_processing #endif +#include <new> #include <QtCore/qatomic.h> #include <QtCore/qobject.h> // for qobject_cast @@ -93,12 +94,11 @@ namespace QtSharedPointer { template <class T> class InternalRefCount; template <class T> class ExternalRefCount; - template <class X, class T> QSharedPointer<X> strongRefFromWeakHelper(const QWeakPointer<T> &, X*); template <class X, class Y> QSharedPointer<X> copyAndSetPointer(X * ptr, const QSharedPointer<Y> &src); // used in debug mode to verify the reuse of pointers - Q_CORE_EXPORT void internalSafetyCheckAdd(const volatile void *); - Q_CORE_EXPORT void internalSafetyCheckRemove(const volatile void *); + Q_CORE_EXPORT void internalSafetyCheckAdd2(const void *, const volatile void *); + Q_CORE_EXPORT void internalSafetyCheckRemove2(const void *); template <class T, typename Klass, typename RetVal> inline void executeDeleter(T *t, RetVal (Klass:: *memberDeleter)()) @@ -106,13 +106,15 @@ namespace QtSharedPointer { template <class T, typename Deleter> inline void executeDeleter(T *t, Deleter d) { d(t); } + template <class T> inline void normalDeleter(T *t) { delete t; } + + // this uses partial template specialization + // the only compilers that didn't support this were MSVC 6.0 and 2002 + template <class T> struct RemovePointer; + template <class T> struct RemovePointer<T *> { typedef T Type; }; + template <class T> struct RemovePointer<QSharedPointer<T> > { typedef T Type; }; + template <class T> struct RemovePointer<QWeakPointer<T> > { typedef T Type; }; - // - // Depending on its template parameter, QSharedPointer derives from either - // QtSharedPointer::InternalRefCount or from QtSharedPointer::ExternalRefCount. - // Both of these classes derive from QtSharedPointer::Basic, which provides common - // operations, - // template <class T> class Basic { @@ -128,34 +130,14 @@ namespace QtSharedPointer { inline T *operator->() const { return data(); } protected: - inline Basic() : value(0) { } + inline Basic(T *ptr = 0) : value(ptr) { } + inline Basic(Qt::Initialization) { } // ~Basic(); - inline void verifyReconstruction(const T *ptr) - { - Q_ASSERT_X(!ptr || value != ptr, "QSharedPointer", - "QSharedPointer violation: you cannot create two QSharedPointer objects " - "from the same pointer"); - - // make use of the "ptr" variable in the no-op statement below - // since this function is in a public header, we don't - // want warnings on "unused variables" to show up everywhere - ptr = 0; - } - inline void internalConstruct(T *ptr) { -#ifdef QT_SHAREDPOINTER_TRACK_POINTERS - if (ptr) internalSafetyCheckAdd(ptr); -#endif value = ptr; } - inline void internalDestroy() - { -#ifdef QT_SHAREDPOINTER_TRACK_POINTERS - if (value) internalSafetyCheckRemove(value); -#endif - } #if defined(Q_NO_TEMPLATE_FRIENDS) public: @@ -168,62 +150,200 @@ namespace QtSharedPointer { struct ExternalRefCountData { - QAtomicInt weakref; - QAtomicInt strongref; + QBasicAtomicInt weakref; + QBasicAtomicInt strongref; - inline ExternalRefCountData() : weakref(1), strongref(1) { } - virtual inline ~ExternalRefCountData() { Q_ASSERT(!weakref); Q_ASSERT(!strongref); } + inline ExternalRefCountData() + { + QBasicAtomicInt proto = Q_BASIC_ATOMIC_INITIALIZER(1); + weakref = strongref = proto; + } + inline ExternalRefCountData(Qt::Initialization) { } + virtual inline ~ExternalRefCountData() { Q_ASSERT(!weakref); Q_ASSERT(strongref <= 0); } virtual inline bool destroy() { return false; } + +#ifndef QT_NO_QOBJECT + Q_CORE_EXPORT static ExternalRefCountData *getAndRef(const QObject *); + Q_CORE_EXPORT void setQObjectShared(const QObject *, bool enable); +#endif + inline void setQObjectShared(...) { } }; + // sizeof(ExternalRefCount) = 12 (32-bit) / 16 (64-bit) template <class T, typename Deleter> - struct ExternalRefCountWithSpecializedDeleter: public ExternalRefCountData + struct CustomDeleter { - T *ptr; Deleter deleter; + T *ptr; + + inline CustomDeleter(T *p, Deleter d) : deleter(d), ptr(p) {} + }; + // sizeof(CustomDeleter) = sizeof(Deleter) + sizeof(void*) + // for Deleter = function pointer: 8 (32-bit) / 16 (64-bit) + // for Deleter = PMF: 12 (32-bit) / 24 (64-bit) (GCC) - inline ExternalRefCountWithSpecializedDeleter(T *p, Deleter d) - : ptr(p), deleter(d) + struct ExternalRefCountWithDestroyFn: public ExternalRefCountData + { + typedef void (*DestroyerFn)(ExternalRefCountData *); + DestroyerFn destroyer; + + inline ExternalRefCountWithDestroyFn(DestroyerFn d) + : destroyer(d) { } - inline bool destroy() { executeDeleter(ptr, deleter); return true; } + + inline bool destroy() { destroyer(this); return true; } + inline void operator delete(void *ptr) { ::operator delete(ptr); } + }; + // sizeof(ExternalRefCountWithDestroyFn) = 16 (32-bit) / 24 (64-bit) + + template <class T, typename Deleter> + struct ExternalRefCountWithCustomDeleter: public ExternalRefCountWithDestroyFn + { + typedef ExternalRefCountWithCustomDeleter Self; + typedef ExternalRefCountWithDestroyFn Parent; + typedef CustomDeleter<T, Deleter> Next; + Next extra; + + static inline void deleter(ExternalRefCountData *self) + { + Self *realself = static_cast<Self *>(self); + executeDeleter(realself->extra.ptr, realself->extra.deleter); + + // delete the deleter too + realself->extra.~Next(); + } + static void safetyCheckDeleter(ExternalRefCountData *self) + { + internalSafetyCheckRemove2(self); + deleter(self); + } + + static inline Self *create(T *ptr, Deleter userDeleter) + { +# ifdef QT_SHAREDPOINTER_TRACK_POINTERS + DestroyerFn destroy = &safetyCheckDeleter; +# else + DestroyerFn destroy = &deleter; +# endif + Self *d = static_cast<Self *>(::operator new(sizeof(Self))); + + // initialize the two sub-objects + new (&d->extra) Next(ptr, userDeleter); + new (d) Parent(destroy); // can't throw + + return d; + } + private: + // prevent construction and the emission of virtual symbols + ExternalRefCountWithCustomDeleter(); + ~ExternalRefCountWithCustomDeleter(); + }; + + template <class T> + struct ExternalRefCountWithContiguousData: public ExternalRefCountWithDestroyFn + { + typedef ExternalRefCountWithDestroyFn Parent; + T data; + + static void deleter(ExternalRefCountData *self) + { + ExternalRefCountWithContiguousData *that = + static_cast<ExternalRefCountWithContiguousData *>(self); + that->data.~T(); + } + static void safetyCheckDeleter(ExternalRefCountData *self) + { + internalSafetyCheckRemove2(self); + deleter(self); + } + + static inline ExternalRefCountData *create(T **ptr) + { +# ifdef QT_SHAREDPOINTER_TRACK_POINTERS + DestroyerFn destroy = &safetyCheckDeleter; +# else + DestroyerFn destroy = &deleter; +# endif + ExternalRefCountWithContiguousData *d = + static_cast<ExternalRefCountWithContiguousData *>(::operator new(sizeof(ExternalRefCountWithContiguousData))); + + // initialize the d-pointer sub-object + // leave d->data uninitialized + new (d) Parent(destroy); // can't throw + + *ptr = &d->data; + return d; + } + + private: + // prevent construction and the emission of virtual symbols + ExternalRefCountWithContiguousData(); + ~ExternalRefCountWithContiguousData(); }; template <class T> class ExternalRefCount: public Basic<T> { - typedef ExternalRefCountData Data; - typedef void (*DeleterFunction)(T *); protected: + typedef ExternalRefCountData Data; + inline void ref() const { d->weakref.ref(); d->strongref.ref(); } inline bool deref() { - if (!d->strongref.deref()) - this->internalDestroy(); + if (!d->strongref.deref()) { + internalDestroy(); + } return d->weakref.deref(); } inline void internalConstruct(T *ptr) { - Basic<T>::internalConstruct(ptr); - Q_ASSERT(!d); +#ifdef QT_SHAREDPOINTER_TRACK_POINTERS + internalConstruct<void (*)(T *)>(ptr, normalDeleter); +#else if (ptr) d = new Data; + else + d = 0; + internalFinishConstruction(ptr); +#endif } template <typename Deleter> inline void internalConstruct(T *ptr, Deleter deleter) { - Basic<T>::internalConstruct(ptr); - Q_ASSERT(!d); if (ptr) - d = new ExternalRefCountWithSpecializedDeleter<T, Deleter>(ptr, deleter); + d = ExternalRefCountWithCustomDeleter<T, Deleter>::create(ptr, deleter); + else + d = 0; + internalFinishConstruction(ptr); + } + + inline void internalCreate() + { + T *ptr; + d = ExternalRefCountWithContiguousData<T>::create(&ptr); + Basic<T>::internalConstruct(ptr); + } + + inline void internalFinishConstruction(T *ptr) + { + Basic<T>::internalConstruct(ptr); + if (ptr) d->setQObjectShared(ptr, true); +#ifdef QT_SHAREDPOINTER_TRACK_POINTERS + if (ptr) internalSafetyCheckAdd2(d, ptr); +#endif } inline ExternalRefCount() : d(0) { } - inline ~ExternalRefCount() { if (d && !deref()) delete d; } + inline ExternalRefCount(Qt::Initialization i) : Basic<T>(i) { } inline ExternalRefCount(const ExternalRefCount<T> &other) : Basic<T>(other), d(other.d) { if (d) ref(); } + template <class X> + inline ExternalRefCount(const ExternalRefCount<X> &other) : Basic<T>(other.value), d(other.d) + { if (d) ref(); } + inline ~ExternalRefCount() { if (d && !deref()) delete d; } template <class X> inline void internalCopy(const ExternalRefCount<X> &other) @@ -233,30 +353,35 @@ namespace QtSharedPointer { inline void internalDestroy() { - Basic<T>::internalDestroy(); if (!d->destroy()) delete this->value; } - private: #if defined(Q_NO_TEMPLATE_FRIENDS) public: #else template <class X> friend class ExternalRefCount; template <class X> friend class QWeakPointer; template <class X, class Y> friend QSharedPointer<X> copyAndSetPointer(X * ptr, const QSharedPointer<Y> &src); - template <class X, class Y> friend QSharedPointer<X> QtSharedPointer::strongRefFromWeakHelper(const QWeakPointer<Y> &src, X *); #endif inline void internalSet(Data *o, T *actual) { - if (d == o) return; - if (o && !o->strongref) - o = 0; if (o) { - verifyReconstruction(actual); - o->weakref.ref(); - o->strongref.ref(); + // increase the strongref, but never up from zero + // or less (-1 is used by QWeakPointer on untracked QObject) + register int tmp = o->strongref; + while (tmp > 0) { + // try to increment from "tmp" to "tmp + 1" + if (o->strongref.testAndSetRelaxed(tmp, tmp + 1)) + break; // succeeded + tmp = o->strongref; // failed, try again + } + + if (tmp > 0) + o->weakref.ref(); + else + o = 0; } if (d && !deref()) delete d; @@ -264,9 +389,6 @@ namespace QtSharedPointer { this->value = d && d->strongref ? actual : 0; } -#if defined(QT_BUILD_INTERNAL) - public: -#endif Data *d; private: @@ -282,7 +404,8 @@ public: inline QSharedPointer() { } // inline ~QSharedPointer() { } - inline explicit QSharedPointer(T *ptr) { internalConstruct(ptr); } + inline explicit QSharedPointer(T *ptr) : BaseClass(Qt::Uninitialized) + { internalConstruct(ptr); } template <typename Deleter> inline QSharedPointer(T *ptr, Deleter d) { internalConstruct(ptr, d); } @@ -294,13 +417,9 @@ public: return *this; } - inline QSharedPointer(const QWeakPointer<T> &other) - { *this = QtSharedPointer::strongRefFromWeakHelper(other, static_cast<T*>(0)); } - inline QSharedPointer<T> &operator=(const QWeakPointer<T> &other) - { *this = QtSharedPointer::strongRefFromWeakHelper(other, static_cast<T*>(0)); return *this; } - template <class X> - inline QSharedPointer(const QSharedPointer<X> &other) { *this = other; } + inline QSharedPointer(const QSharedPointer<X> &other) : BaseClass(other) + { } template <class X> inline QSharedPointer<T> &operator=(const QSharedPointer<X> &other) @@ -311,12 +430,12 @@ public: } template <class X> - inline QSharedPointer(const QWeakPointer<X> &other) - { *this = QtSharedPointer::strongRefFromWeakHelper(other, static_cast<T *>(0)); } + inline QSharedPointer(const QWeakPointer<X> &other) : BaseClass(Qt::Uninitialized) + { this->d = 0; *this = other; } template <class X> inline QSharedPointer<T> &operator=(const QWeakPointer<X> &other) - { *this = strongRefFromWeakHelper(other, static_cast<T *>(0)); return *this; } + { internalSet(other.d, other.value); return *this; } template <class X> QSharedPointer<X> staticCast() const @@ -347,6 +466,21 @@ public: inline void clear() { *this = QSharedPointer<T>(); } QWeakPointer<T> toWeakRef() const; + +protected: + inline QSharedPointer(Qt::Initialization i) : BaseClass(i) {} + +public: + static inline QSharedPointer<T> create() + { + QSharedPointer<T> result(Qt::Uninitialized); + result.internalCreate(); + + // now initialize the data + new (result.data()) T(); + result.internalFinishConstruction(result.data()); + return result; + } }; template <class T> @@ -359,9 +493,19 @@ public: inline bool isNull() const { return d == 0 || d->strongref == 0 || value == 0; } inline operator RestrictedBool() const { return isNull() ? 0 : &QWeakPointer::value; } inline bool operator !() const { return isNull(); } + inline T *data() const { return d == 0 || d->strongref == 0 ? 0 : value; } inline QWeakPointer() : d(0), value(0) { } inline ~QWeakPointer() { if (d && !d->weakref.deref()) delete d; } + + // special constructor that is enabled only if X derives from QObject + template <class X> + inline QWeakPointer(X *ptr) : d(ptr ? d->getAndRef(ptr) : 0), value(ptr) + { } + template <class X> + inline QWeakPointer &operator=(X *ptr) + { return *this = QWeakPointer(ptr); } + inline QWeakPointer(const QWeakPointer<T> &o) : d(o.d), value(o.value) { if (d) d->weakref.ref(); } inline QWeakPointer<T> &operator=(const QWeakPointer<T> &o) @@ -413,7 +557,7 @@ public: template <class X> inline bool operator==(const QSharedPointer<X> &o) const - { return d == o.d && value == static_cast<const T *>(o.data()); } + { return d == o.d; } template <class X> inline bool operator!=(const QSharedPointer<X> &o) const @@ -428,7 +572,7 @@ private: #if defined(Q_NO_TEMPLATE_FRIENDS) public: #else - template <class X, class Y> friend QSharedPointer<X> QtSharedPointer::strongRefFromWeakHelper(const QWeakPointer<Y> &src, X *); + template <class X> friend class QSharedPointer; #endif inline void internalSet(Data *o, T *actual) @@ -505,14 +649,6 @@ namespace QtSharedPointer { result.internalSet(src.d, ptr); return result; } - template <class X, class T> - Q_INLINE_TEMPLATE QSharedPointer<X> strongRefFromWeakHelper - (const QT_PREPEND_NAMESPACE(QWeakPointer<T>) &src, X *) - { - QSharedPointer<X> result; - result.internalSet(src.d, src.value); - return result; - } } // cast operators @@ -572,14 +708,6 @@ Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerObjectCast(const QWeakPointer< return qSharedPointerObjectCast<X>(src.toStrongRef()); } -# ifndef QT_NO_PARTIAL_TEMPLATE_SPECIALIZATION -namespace QtSharedPointer { - template <class T> struct RemovePointer; - template <class T> struct RemovePointer<T *> { typedef T Type; }; - template <class T> struct RemovePointer<QSharedPointer<T> > { typedef T Type; }; - template <class T> struct RemovePointer<QWeakPointer<T> > { typedef T Type; }; -} - template <class X, class T> inline QSharedPointer<typename QtSharedPointer::RemovePointer<X>::Type> qobject_cast(const QSharedPointer<T> &src) @@ -592,7 +720,6 @@ qobject_cast(const QWeakPointer<T> &src) { return qSharedPointerObjectCast<typename QtSharedPointer::RemovePointer<X>::Type, T>(src); } -# endif #endif diff --git a/src/corelib/tools/qstringbuilder.h b/src/corelib/tools/qstringbuilder.h index 3b43253..463c32d 100644 --- a/src/corelib/tools/qstringbuilder.h +++ b/src/corelib/tools/qstringbuilder.h @@ -163,7 +163,7 @@ template <> struct QConcatenable<QString> static inline void appendTo(const QString &a, QChar *&out) { const int n = a.size(); - memcpy(out, (char*)a.constData(), sizeof(QChar) * n); + memcpy(out, reinterpret_cast<const char*>(a.constData()), sizeof(QChar) * n); out += n; } }; @@ -175,7 +175,7 @@ template <> struct QConcatenable<QStringRef> static inline void appendTo(QStringRef a, QChar *&out) { const int n = a.size(); - memcpy(out, (char*)a.constData(), sizeof(QChar) * n); + memcpy(out, reinterpret_cast<const char*>(a.constData()), sizeof(QChar) * n); out += n; } }; diff --git a/src/corelib/tools/qvector.h b/src/corelib/tools/qvector.h index 51a6709..dcd87b7 100644 --- a/src/corelib/tools/qvector.h +++ b/src/corelib/tools/qvector.h @@ -252,11 +252,7 @@ public: typedef const value_type* const_pointer; typedef value_type& reference; typedef const value_type& const_reference; -#ifndef QT_NO_STL typedef ptrdiff_t difference_type; -#else - typedef int difference_type; -#endif typedef iterator Iterator; typedef const_iterator ConstIterator; typedef int size_type; diff --git a/src/corelib/tools/tools.pri b/src/corelib/tools/tools.pri index 08c94ac..44fbb62 100644 --- a/src/corelib/tools/tools.pri +++ b/src/corelib/tools/tools.pri @@ -109,4 +109,4 @@ SOURCES += ../3rdparty/harfbuzz/src/harfbuzz-buffer.c \ tools/qharfbuzz.cpp HEADERS += tools/qharfbuzz_p.h -!macx-icc:unix:LIBS += -lm +!macx-icc:!vxworks:unix:LIBS += -lm diff --git a/src/corelib/xml/qxmlstream.cpp b/src/corelib/xml/qxmlstream.cpp index 42ed04e..3e8f73e 100644 --- a/src/corelib/xml/qxmlstream.cpp +++ b/src/corelib/xml/qxmlstream.cpp @@ -334,12 +334,17 @@ QXmlStreamEntityResolver *QXmlStreamReader::entityResolver() const from the PrematureEndOfDocumentError error and continues parsing the new data with the next call to readNext(). - For example, if you read data from the network using QHttp, you - would connect its \l{QHttp::readyRead()}{readyRead()} signal to a - custom slot. In this slot, you read all available data with - \l{QHttp::readAll()}{readAll()} and pass it to the XML stream reader - using addData(). Then you call your custom parsing function that - reads the XML events from the reader. + For example, if your application reads data from the network using a + \l{QNetworkAccessManager} {network access manager}, you would issue + a \l{QNetworkRequest} {network request} to the manager and receive a + \l{QNetworkReply} {network reply} in return. Since a QNetworkReply + is a QIODevice, you connect its \l{QNetworkReply::readyRead()} + {readyRead()} signal to a custom slot, e.g. \c{slotReadyRead()} in + the code snippet shown in the discussion for QNetworkAccessManager. + In this slot, you read all available data with + \l{QNetworkReply::readAll()} {readAll()} and pass it to the XML + stream reader using addData(). Then you call your custom parsing + function that reads the XML events from the reader. \section1 Performance and memory consumption diff --git a/src/corelib/xml/qxmlstream_p.h b/src/corelib/xml/qxmlstream_p.h index f1614ea..7a4d2a8 100644 --- a/src/corelib/xml/qxmlstream_p.h +++ b/src/corelib/xml/qxmlstream_p.h @@ -54,6 +54,10 @@ #ifndef QXMLSTREAM_P_H #define QXMLSTREAM_P_H +#if defined(Q_OS_VXWORKS) && defined(ERROR) +# undef ERROR +#endif + class QXmlStreamReader_Table { public: |