summaryrefslogtreecommitdiffstats
path: root/src/corelib
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib')
-rw-r--r--src/corelib/animation/qabstractanimation.cpp30
-rw-r--r--src/corelib/animation/qabstractanimation_p.h3
-rw-r--r--src/corelib/animation/qparallelanimationgroup.cpp3
-rw-r--r--src/corelib/animation/qvariantanimation.cpp2
-rw-r--r--src/corelib/arch/qatomic_vxworks.h2
-rw-r--r--src/corelib/global/qglobal.cpp4
-rw-r--r--src/corelib/global/qglobal.h21
-rw-r--r--src/corelib/global/qnamespace.h16
-rw-r--r--src/corelib/io/qfilesystemwatcher_fsevents.cpp7
-rw-r--r--src/corelib/io/qfilesystemwatcher_fsevents_p.h1
-rw-r--r--src/corelib/kernel/kernel.pri5
-rw-r--r--src/corelib/kernel/qabstractitemmodel.cpp52
-rw-r--r--src/corelib/kernel/qabstractitemmodel.h4
-rw-r--r--src/corelib/kernel/qabstractitemmodel_p.h5
-rw-r--r--src/corelib/kernel/qcore_unix.cpp73
-rw-r--r--src/corelib/kernel/qcore_unix_p.h38
-rw-r--r--src/corelib/kernel/qcoreevent.cpp2
-rw-r--r--src/corelib/kernel/qcoreevent.h2
-rw-r--r--src/corelib/kernel/qeventdispatcher_glib.cpp1
-rw-r--r--src/corelib/kernel/qeventdispatcher_unix_p.h3
-rw-r--r--src/corelib/kernel/qfunctions_vxworks.cpp4
-rw-r--r--src/corelib/kernel/qfunctions_vxworks.h2
-rw-r--r--src/corelib/kernel/qguard_p.h157
-rw-r--r--src/corelib/kernel/qmetaobject.cpp111
-rw-r--r--src/corelib/kernel/qmetaobject.h4
-rw-r--r--src/corelib/kernel/qobject.cpp132
-rw-r--r--src/corelib/kernel/qobject.h11
-rw-r--r--src/corelib/kernel/qobject_p.h148
-rw-r--r--src/corelib/kernel/qobjectdefs.h5
-rw-r--r--src/corelib/statemachine/qabstracttransition.cpp22
-rw-r--r--src/corelib/statemachine/qabstracttransition.h3
-rw-r--r--src/corelib/statemachine/qeventtransition.cpp30
-rw-r--r--src/corelib/statemachine/qeventtransition.h5
-rw-r--r--src/corelib/statemachine/qsignalevent.h6
-rw-r--r--src/corelib/statemachine/qsignaltransition.cpp15
-rw-r--r--src/corelib/statemachine/qsignaltransition.h3
-rw-r--r--src/corelib/statemachine/qstate.cpp6
-rw-r--r--src/corelib/statemachine/qstatemachine.cpp104
-rw-r--r--src/corelib/statemachine/qstatemachine_p.h12
-rw-r--r--src/corelib/tools/qbytedata_p.h12
-rw-r--r--src/corelib/tools/qcontiguouscache.h7
-rw-r--r--src/corelib/tools/qshareddata.cpp2
-rw-r--r--src/corelib/tools/qsharedpointer.cpp149
-rw-r--r--src/corelib/tools/qsharedpointer.h1
-rw-r--r--src/corelib/tools/qsharedpointer_impl.h192
45 files changed, 992 insertions, 425 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/qatomic_vxworks.h b/src/corelib/arch/qatomic_vxworks.h
index 573a44d..b441210 100644
--- a/src/corelib/arch/qatomic_vxworks.h
+++ b/src/corelib/arch/qatomic_vxworks.h
@@ -34,7 +34,7 @@
** 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 qt-sales@nokia.com.
+** contact the sales department at http://www.qtsoftware.com/contact.
** $QT_END_LICENSE$
**
****************************************************************************/
diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp
index 776a740..63941ef 100644
--- a/src/corelib/global/qglobal.cpp
+++ b/src/corelib/global/qglobal.cpp
@@ -1083,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:
@@ -1092,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:
diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h
index 8263bae..1711f16 100644
--- a/src/corelib/global/qglobal.h
+++ b/src/corelib/global/qglobal.h
@@ -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,11 +311,8 @@ 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
@@ -1176,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
@@ -1220,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
@@ -1246,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
@@ -1259,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
@@ -2308,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 \
@@ -2329,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 \
@@ -2377,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
diff --git a/src/corelib/global/qnamespace.h b/src/corelib/global/qnamespace.h
index 7770fd6..f172d77 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,
@@ -1591,6 +1606,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/qfilesystemwatcher_fsevents.cpp b/src/corelib/io/qfilesystemwatcher_fsevents.cpp
index 3e0aee8..cb276b7 100644
--- a/src/corelib/io/qfilesystemwatcher_fsevents.cpp
+++ b/src/corelib/io/qfilesystemwatcher_fsevents.cpp
@@ -422,9 +422,12 @@ void QFSEventsFileSystemWatcherEngine::fseventsCallback(ConstFSEventStreamRef ,
void QFSEventsFileSystemWatcherEngine::stop()
{
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
+ QMutexLocker locker(&mutex);
stopFSStream(fsStream);
- if (threadsRunLoop)
+ if (threadsRunLoop) {
CFRunLoopStop(threadsRunLoop);
+ waitForStop.wait(&mutex);
+ }
#endif
}
@@ -461,6 +464,8 @@ void QFSEventsFileSystemWatcherEngine::run()
// immediately.
CFRunLoopRun();
threadsRunLoop = 0;
+ QMutexLocker locker(&mutex);
+ waitForStop.wakeAll();
#endif
}
diff --git a/src/corelib/io/qfilesystemwatcher_fsevents_p.h b/src/corelib/io/qfilesystemwatcher_fsevents_p.h
index 4770867..ffc0c68 100644
--- a/src/corelib/io/qfilesystemwatcher_fsevents_p.h
+++ b/src/corelib/io/qfilesystemwatcher_fsevents_p.h
@@ -114,6 +114,7 @@ private:
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;
diff --git a/src/corelib/kernel/kernel.pri b/src/corelib/kernel/kernel.pri
index 7177293..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 += \
diff --git a/src/corelib/kernel/qabstractitemmodel.cpp b/src/corelib/kernel/qabstractitemmodel.cpp
index 3d9263e..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.
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 b57d385..efa9c6d 100644
--- a/src/corelib/kernel/qcore_unix.cpp
+++ b/src/corelib/kernel/qcore_unix.cpp
@@ -161,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 dceb73a..3bdd5ec 100644
--- a/src/corelib/kernel/qcore_unix_p.h
+++ b/src/corelib/kernel/qcore_unix_p.h
@@ -73,32 +73,16 @@
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);
@@ -190,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
@@ -246,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));
@@ -323,6 +307,10 @@ static inline pid_t qt_safe_waitpid(pid_t pid, int *status, int options)
#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,
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_p.h b/src/corelib/kernel/qeventdispatcher_unix_p.h
index 9c67c70..5e016d3 100644
--- a/src/corelib/kernel/qeventdispatcher_unix_p.h
+++ b/src/corelib/kernel/qeventdispatcher_unix_p.h
@@ -69,9 +69,6 @@
#endif
QT_BEGIN_NAMESPACE
-#if !defined(_POSIX_MONOTONIC_CLOCK)
-# define _POSIX_MONOTONIC_CLOCK -1
-#endif
// internal timer info
struct QTimerInfo {
diff --git a/src/corelib/kernel/qfunctions_vxworks.cpp b/src/corelib/kernel/qfunctions_vxworks.cpp
index 6d5e7cc..def8f4c 100644
--- a/src/corelib/kernel/qfunctions_vxworks.cpp
+++ b/src/corelib/kernel/qfunctions_vxworks.cpp
@@ -1,7 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** Contact: Qt Software Information (qt-info@nokia.com)
+** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtCore module of the Qt Toolkit.
**
@@ -34,7 +34,7 @@
** 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 qt-sales@nokia.com.
+** contact the sales department at http://www.qtsoftware.com/contact.
** $QT_END_LICENSE$
**
****************************************************************************/
diff --git a/src/corelib/kernel/qfunctions_vxworks.h b/src/corelib/kernel/qfunctions_vxworks.h
index cc98948..e31d495 100644
--- a/src/corelib/kernel/qfunctions_vxworks.h
+++ b/src/corelib/kernel/qfunctions_vxworks.h
@@ -34,7 +34,7 @@
** 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 qt-sales@nokia.com.
+** contact the sales department at http://www.qtsoftware.com/contact.
** $QT_END_LICENSE$
**
****************************************************************************/
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..e37b6d3 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));
@@ -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..056dee3 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 { class 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/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 2042288..09d0be0 100644
--- a/src/corelib/statemachine/qstate.cpp
+++ b/src/corelib/statemachine/qstate.cpp
@@ -339,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;
}
@@ -351,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/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp
index a02480b..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;
@@ -1138,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 *) {}
@@ -1146,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);
@@ -1165,11 +1181,19 @@ 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);
@@ -1177,7 +1201,7 @@ void QStateMachinePrivate::_q_start()
applyProperties(transitions, QList<QAbstractState*>() << start,
enteredStates);
#endif
- delete start;
+ removeStartState();
#ifdef QSTATEMACHINE_DEBUG
qDebug() << q << ": initial configuration:" << configuration;
@@ -1277,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);
@@ -1446,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);
@@ -2026,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 cae21aa..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,7 +152,7 @@ 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();
@@ -162,6 +167,7 @@ public:
#endif
State state;
+ QState *_startState;
bool processing;
bool processingScheduled;
bool stop;
@@ -208,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/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/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 59dfffe..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
@@ -897,6 +1019,7 @@ 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();
}
/*!
@@ -961,6 +1084,7 @@ void QtSharedPointer::internalSafetyCheckAdd2(const void *d_ptr, const volatile
kp->dPointers.insert(d_ptr, data);
kp->dataPointers.insert(ptr, d_ptr);
+ Q_ASSERT(kp->dPointers.size() == kp->dataPointers.size());
}
/*!
@@ -985,10 +1109,29 @@ void QtSharedPointer::internalSafetyCheckRemove2(const void *d_ptr)
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 b8f4139..8a34362 100644
--- a/src/corelib/tools/qsharedpointer_impl.h
+++ b/src/corelib/tools/qsharedpointer_impl.h
@@ -94,26 +94,27 @@ 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 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)())
{ (t->*memberDeleter)(); }
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
{
@@ -129,21 +130,10 @@ 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)
{
value = ptr;
@@ -160,14 +150,26 @@ 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 CustomDeleter
@@ -177,6 +179,9 @@ namespace QtSharedPointer {
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)
struct ExternalRefCountWithDestroyFn: public ExternalRefCountData
{
@@ -190,6 +195,7 @@ namespace QtSharedPointer {
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
@@ -203,11 +209,23 @@ namespace QtSharedPointer {
{
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
@@ -234,10 +252,19 @@ namespace QtSharedPointer {
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)));
@@ -258,9 +285,9 @@ namespace QtSharedPointer {
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()
{
@@ -272,42 +299,51 @@ namespace QtSharedPointer {
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;
-#ifdef QT_SHAREDPOINTER_TRACK_POINTERS
- if (ptr) internalSafetyCheckAdd2(d, ptr);
+ 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 = ExternalRefCountWithCustomDeleter<T, Deleter>::create(ptr, deleter);
-#ifdef QT_SHAREDPOINTER_TRACK_POINTERS
- if (ptr) internalSafetyCheckAdd2(d, ptr);
-#endif
+ 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)
@@ -317,32 +353,35 @@ namespace QtSharedPointer {
inline void internalDestroy()
{
-#ifdef QT_SHAREDPOINTER_TRACK_POINTERS
- internalSafetyCheckRemove2(d);
-#endif
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;
@@ -350,9 +389,6 @@ namespace QtSharedPointer {
this->value = d && d->strongref ? actual : 0;
}
-#if defined(QT_BUILD_INTERNAL)
- public:
-#endif
Data *d;
private:
@@ -368,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); }
@@ -380,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)
@@ -397,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
@@ -434,14 +467,18 @@ public:
QWeakPointer<T> toWeakRef() const;
+protected:
+ inline QSharedPointer(Qt::Initialization i) : BaseClass(i) {}
+
public:
static inline QSharedPointer<T> create()
{
- QSharedPointer<T> result;
+ QSharedPointer<T> result(Qt::Uninitialized);
result.internalCreate();
// now initialize the data
new (result.data()) T();
+ result.internalFinishConstruction(result.data());
return result;
}
};
@@ -456,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)
@@ -510,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
@@ -525,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)
@@ -602,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
@@ -669,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)
@@ -689,7 +720,6 @@ qobject_cast(const QWeakPointer<T> &src)
{
return qSharedPointerObjectCast<typename QtSharedPointer::RemovePointer<X>::Type, T>(src);
}
-# endif
#endif