summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorRobin Burchell <robin.burchell@collabora.com>2011-10-25 09:51:19 +0200
committerQt by Nokia <qt-info@nokia.com>2011-12-15 13:33:31 +0100
commitf9516e4c8e90995a01ab3b5b892c98ca9c4880fd (patch)
treea8633029e2b0b2300e2dd980bb9bdffe3512e693 /src
parent317ee62d447374b059526174952cea44108ec284 (diff)
Split timer handling out of QEventDispatcherUnix.
This makes it easier to see the guts of the unix event dispatcher, and to experiment with it. Change-Id: I715bb68c4de6798e10bc55304a128b88e0249c63 Reviewed-by: João Abecasis <joao.abecasis@nokia.com>
Diffstat (limited to 'src')
-rw-r--r--src/corelib/kernel/kernel.pri45
-rw-r--r--src/corelib/kernel/qeventdispatcher_unix.cpp322
-rw-r--r--src/corelib/kernel/qeventdispatcher_unix_p.h45
-rw-r--r--src/corelib/kernel/qtimerinfo_unix.cpp376
-rw-r--r--src/corelib/kernel/qtimerinfo_unix_p.h110
5 files changed, 511 insertions, 387 deletions
diff --git a/src/corelib/kernel/kernel.pri b/src/corelib/kernel/kernel.pri
index b67d60bfff..4dbb669ffd 100644
--- a/src/corelib/kernel/kernel.pri
+++ b/src/corelib/kernel/kernel.pri
@@ -100,27 +100,28 @@ nacl {
}
unix:!symbian {
+ SOURCES += \
+ kernel/qcore_unix.cpp \
+ kernel/qcrashhandler.cpp \
+ kernel/qsharedmemory_unix.cpp \
+ kernel/qsystemsemaphore_unix.cpp \
+ kernel/qeventdispatcher_unix.cpp \
+ kernel/qtimerinfo_unix.cpp
+
+ HEADERS += \
+ kernel/qcore_unix_p.h \
+ kernel/qcrashhandler_p.h \
+ kernel/qeventdispatcher_unix_p.h \
+ kernel/qtimerinfo_unix_p.h
+
+ contains(QT_CONFIG, glib) {
SOURCES += \
- kernel/qcore_unix.cpp \
- kernel/qcrashhandler.cpp \
- kernel/qsharedmemory_unix.cpp \
- kernel/qsystemsemaphore_unix.cpp
+ kernel/qeventdispatcher_glib.cpp
HEADERS += \
- kernel/qcore_unix_p.h \
- kernel/qcrashhandler_p.h
-
- contains(QT_CONFIG, glib) {
- SOURCES += \
- kernel/qeventdispatcher_glib.cpp
- HEADERS += \
- kernel/qeventdispatcher_glib_p.h
- QMAKE_CXXFLAGS += $$QT_CFLAGS_GLIB
- LIBS_PRIVATE +=$$QT_LIBS_GLIB
- }
- SOURCES += \
- kernel/qeventdispatcher_unix.cpp
- HEADERS += \
- kernel/qeventdispatcher_unix_p.h
+ kernel/qeventdispatcher_glib_p.h
+ QMAKE_CXXFLAGS += $$QT_CFLAGS_GLIB
+ LIBS_PRIVATE +=$$QT_LIBS_GLIB
+ }
contains(QT_CONFIG, clock-gettime):include($$QT_SOURCE_TREE/config.tests/unix/clock-gettime/clock-gettime.pri)
}
@@ -155,11 +156,13 @@ integrity {
kernel/qcrashhandler.cpp \
kernel/qsharedmemory_unix.cpp \
kernel/qsystemsemaphore_unix.cpp \
- kernel/qeventdispatcher_unix.cpp
+ kernel/qeventdispatcher_unix.cpp \
+ kernel/qtimerinfo_unix.cpp
HEADERS += \
kernel/qcore_unix_p.h \
kernel/qcrashhandler_p.h \
- kernel/qeventdispatcher_unix_p.h
+ kernel/qeventdispatcher_unix_p.h \
+ kernel/qtimerinfo_unix_p.h
contains(QT_CONFIG, clock-gettime):include($$QT_SOURCE_TREE/config.tests/unix/clock-gettime/clock-gettime.pri)
}
diff --git a/src/corelib/kernel/qeventdispatcher_unix.cpp b/src/corelib/kernel/qeventdispatcher_unix.cpp
index 27efac6985..3420990969 100644
--- a/src/corelib/kernel/qeventdispatcher_unix.cpp
+++ b/src/corelib/kernel/qeventdispatcher_unix.cpp
@@ -72,8 +72,6 @@
QT_BEGIN_NAMESPACE
-Q_CORE_EXPORT bool qt_disable_lowpriority_timers=false;
-
/*****************************************************************************
UNIX signal handling
*****************************************************************************/
@@ -309,326 +307,6 @@ int QEventDispatcherUNIXPrivate::doSelect(QEventLoop::ProcessEventsFlags flags,
return (nevents + q->activateSocketNotifiers());
}
-/*
- * Internal functions for manipulating timer data structures. The
- * timerBitVec array is used for keeping track of timer identifiers.
- */
-
-QTimerInfoList::QTimerInfoList()
-{
-#if (_POSIX_MONOTONIC_CLOCK-0 <= 0) && !defined(Q_OS_MAC) && !defined(Q_OS_NACL)
- if (!QElapsedTimer::isMonotonic()) {
- // not using monotonic timers, initialize the timeChanged() machinery
- previousTime = qt_gettime();
-
- tms unused;
- previousTicks = times(&unused);
-
- ticksPerSecond = sysconf(_SC_CLK_TCK);
- msPerTick = 1000/ticksPerSecond;
- } else {
- // detected monotonic timers
- previousTime.tv_sec = previousTime.tv_usec = 0;
- previousTicks = 0;
- ticksPerSecond = 0;
- msPerTick = 0;
- }
-#endif
-
- firstTimerInfo = 0;
-}
-
-timeval QTimerInfoList::updateCurrentTime()
-{
- return (currentTime = qt_gettime());
-}
-
-#if ((_POSIX_MONOTONIC_CLOCK-0 <= 0) && !defined(Q_OS_MAC) && !defined(Q_OS_INTEGRITY)) || defined(QT_BOOTSTRAPPED)
-
-template <>
-timeval qAbs(const timeval &t)
-{
- timeval tmp = t;
- if (tmp.tv_sec < 0) {
- tmp.tv_sec = -tmp.tv_sec - 1;
- tmp.tv_usec -= 1000000;
- }
- if (tmp.tv_sec == 0 && tmp.tv_usec < 0) {
- tmp.tv_usec = -tmp.tv_usec;
- }
- return normalizedTimeval(tmp);
-}
-
-/*
- Returns true if the real time clock has changed by more than 10%
- relative to the processor time since the last time this function was
- called. This presumably means that the system time has been changed.
-
- If /a delta is nonzero, delta is set to our best guess at how much the system clock was changed.
-*/
-bool QTimerInfoList::timeChanged(timeval *delta)
-{
-#ifdef Q_OS_NACL
- Q_UNUSED(delta)
- return false; // Calling "times" crashes.
-#endif
- struct tms unused;
- clock_t currentTicks = times(&unused);
-
- clock_t elapsedTicks = currentTicks - previousTicks;
- timeval elapsedTime = currentTime - previousTime;
-
- timeval elapsedTimeTicks;
- elapsedTimeTicks.tv_sec = elapsedTicks / ticksPerSecond;
- elapsedTimeTicks.tv_usec = (((elapsedTicks * 1000) / ticksPerSecond) % 1000) * 1000;
-
- timeval dummy;
- if (!delta)
- delta = &dummy;
- *delta = elapsedTime - elapsedTimeTicks;
-
- previousTicks = currentTicks;
- previousTime = currentTime;
-
- // If tick drift is more than 10% off compared to realtime, we assume that the clock has
- // been set. Of course, we have to allow for the tick granularity as well.
- timeval tickGranularity;
- tickGranularity.tv_sec = 0;
- tickGranularity.tv_usec = msPerTick * 1000;
- return elapsedTimeTicks < ((qAbs(*delta) - tickGranularity) * 10);
-}
-
-void QTimerInfoList::repairTimersIfNeeded()
-{
- if (QElapsedTimer::isMonotonic())
- return;
- timeval delta;
- if (timeChanged(&delta))
- timerRepair(delta);
-}
-
-#else // !(_POSIX_MONOTONIC_CLOCK-0 <= 0) && !defined(QT_BOOTSTRAPPED)
-
-void QTimerInfoList::repairTimersIfNeeded()
-{
-}
-
-#endif
-
-/*
- insert timer info into list
-*/
-void QTimerInfoList::timerInsert(QTimerInfo *ti)
-{
- int index = size();
- while (index--) {
- register const QTimerInfo * const t = at(index);
- if (!(ti->timeout < t->timeout))
- break;
- }
- insert(index+1, ti);
-}
-
-/*
- repair broken timer
-*/
-void QTimerInfoList::timerRepair(const timeval &diff)
-{
- // repair all timers
- for (int i = 0; i < size(); ++i) {
- register QTimerInfo *t = at(i);
- t->timeout = t->timeout + diff;
- }
-}
-
-static timeval roundToMillisecond(timeval val)
-{
- // always round up
- // worst case scenario is that the first trigger of a 1-ms timer is 0.999 ms late
-
- int us = val.tv_usec % 1000;
- val.tv_usec += 1000 - us;
- return normalizedTimeval(val);
-}
-
-/*
- Returns the time to wait for the next timer, or null if no timers
- are waiting.
-*/
-bool QTimerInfoList::timerWait(timeval &tm)
-{
- timeval currentTime = updateCurrentTime();
- repairTimersIfNeeded();
-
- // Find first waiting timer not already active
- QTimerInfo *t = 0;
- for (QTimerInfoList::const_iterator it = constBegin(); it != constEnd(); ++it) {
- if (!(*it)->activateRef) {
- t = *it;
- break;
- }
- }
-
- if (!t)
- return false;
-
- if (currentTime < t->timeout) {
- // time to wait
- tm = roundToMillisecond(t->timeout - currentTime);
- } else {
- // no time to wait
- tm.tv_sec = 0;
- tm.tv_usec = 0;
- }
-
- return true;
-}
-
-void QTimerInfoList::registerTimer(int timerId, int interval, QObject *object)
-{
- QTimerInfo *t = new QTimerInfo;
- t->id = timerId;
- t->interval.tv_sec = interval / 1000;
- t->interval.tv_usec = (interval % 1000) * 1000;
- t->timeout = updateCurrentTime() + t->interval;
- t->obj = object;
- t->activateRef = 0;
-
- timerInsert(t);
-}
-
-bool QTimerInfoList::unregisterTimer(int timerId)
-{
- // set timer inactive
- for (int i = 0; i < count(); ++i) {
- register QTimerInfo *t = at(i);
- if (t->id == timerId) {
- // found it
- removeAt(i);
- if (t == firstTimerInfo)
- firstTimerInfo = 0;
- if (t->activateRef)
- *(t->activateRef) = 0;
-
- // release the timer id
- if (!QObjectPrivate::get(t->obj)->inThreadChangeEvent)
- QAbstractEventDispatcherPrivate::releaseTimerId(timerId);
-
- delete t;
- return true;
- }
- }
- // id not found
- return false;
-}
-
-bool QTimerInfoList::unregisterTimers(QObject *object)
-{
- if (isEmpty())
- return false;
- for (int i = 0; i < count(); ++i) {
- register QTimerInfo *t = at(i);
- if (t->obj == object) {
- // object found
- removeAt(i);
- if (t == firstTimerInfo)
- firstTimerInfo = 0;
- if (t->activateRef)
- *(t->activateRef) = 0;
-
- // release the timer id
- if (!QObjectPrivate::get(t->obj)->inThreadChangeEvent)
- QAbstractEventDispatcherPrivate::releaseTimerId(t->id);
-
- delete t;
- // move back one so that we don't skip the new current item
- --i;
- }
- }
- return true;
-}
-
-QList<QPair<int, int> > QTimerInfoList::registeredTimers(QObject *object) const
-{
- QList<QPair<int, int> > list;
- for (int i = 0; i < count(); ++i) {
- register const QTimerInfo * const t = at(i);
- if (t->obj == object)
- list << QPair<int, int>(t->id, t->interval.tv_sec * 1000 + t->interval.tv_usec / 1000);
- }
- return list;
-}
-
-/*
- Activate pending timers, returning how many where activated.
-*/
-int QTimerInfoList::activateTimers()
-{
- if (qt_disable_lowpriority_timers || isEmpty())
- return 0; // nothing to do
-
- int n_act = 0, maxCount = 0;
- firstTimerInfo = 0;
-
- timeval currentTime = updateCurrentTime();
- repairTimersIfNeeded();
-
-
- // Find out how many timer have expired
- for (QTimerInfoList::const_iterator it = constBegin(); it != constEnd(); ++it) {
- if (currentTime < (*it)->timeout)
- break;
- maxCount++;
- }
-
- //fire the timers.
- while (maxCount--) {
- if (isEmpty())
- break;
-
- QTimerInfo *currentTimerInfo = first();
- if (currentTime < currentTimerInfo->timeout)
- break; // no timer has expired
-
- if (!firstTimerInfo) {
- firstTimerInfo = currentTimerInfo;
- } else if (firstTimerInfo == currentTimerInfo) {
- // avoid sending the same timer multiple times
- break;
- } else if (currentTimerInfo->interval < firstTimerInfo->interval
- || currentTimerInfo->interval == firstTimerInfo->interval) {
- firstTimerInfo = currentTimerInfo;
- }
-
- // remove from list
- removeFirst();
-
- // determine next timeout time
- currentTimerInfo->timeout += currentTimerInfo->interval;
- if (currentTimerInfo->timeout < currentTime)
- currentTimerInfo->timeout = currentTime + currentTimerInfo->interval;
-
- // reinsert timer
- timerInsert(currentTimerInfo);
- if (currentTimerInfo->interval.tv_usec > 0 || currentTimerInfo->interval.tv_sec > 0)
- n_act++;
-
- if (!currentTimerInfo->activateRef) {
- // send event, but don't allow it to recurse
- currentTimerInfo->activateRef = &currentTimerInfo;
-
- QTimerEvent e(currentTimerInfo->id);
- QCoreApplication::sendEvent(currentTimerInfo->obj, &e);
-
- if (currentTimerInfo)
- currentTimerInfo->activateRef = 0;
- }
- }
-
- firstTimerInfo = 0;
- return n_act;
-}
-
QEventDispatcherUNIX::QEventDispatcherUNIX(QObject *parent)
: QAbstractEventDispatcher(*new QEventDispatcherUNIXPrivate, parent)
{ }
diff --git a/src/corelib/kernel/qeventdispatcher_unix_p.h b/src/corelib/kernel/qeventdispatcher_unix_p.h
index 122f17f9e9..e96be68db8 100644
--- a/src/corelib/kernel/qeventdispatcher_unix_p.h
+++ b/src/corelib/kernel/qeventdispatcher_unix_p.h
@@ -59,6 +59,7 @@
#include "private/qcore_unix_p.h"
#include "private/qpodlist_p.h"
#include "QtCore/qvarlengtharray.h"
+#include "private/qtimerinfo_unix_p.h"
#if defined(Q_OS_VXWORKS)
# include <sys/times.h>
@@ -71,50 +72,6 @@
QT_BEGIN_NAMESPACE
-// internal timer info
-struct QTimerInfo {
- int id; // - timer identifier
- timeval interval; // - timer interval
- timeval timeout; // - when to sent event
- QObject *obj; // - object to receive event
- QTimerInfo **activateRef; // - ref from activateTimers
-};
-
-class QTimerInfoList : public QList<QTimerInfo*>
-{
-#if ((_POSIX_MONOTONIC_CLOCK-0 <= 0) && !defined(Q_OS_MAC)) || defined(QT_BOOTSTRAPPED)
- timeval previousTime;
- clock_t previousTicks;
- int ticksPerSecond;
- int msPerTick;
-
- bool timeChanged(timeval *delta);
-#endif
-
- // state variables used by activateTimers()
- QTimerInfo *firstTimerInfo;
-
-public:
- QTimerInfoList();
-
- timeval currentTime;
- timeval updateCurrentTime();
-
- // must call updateCurrentTime() first!
- void repairTimersIfNeeded();
-
- bool timerWait(timeval &);
- void timerInsert(QTimerInfo *);
- void timerRepair(const timeval &);
-
- void registerTimer(int timerId, int interval, QObject *object);
- bool unregisterTimer(int timerId);
- bool unregisterTimers(QObject *object);
- QList<QPair<int, int> > registeredTimers(QObject *object) const;
-
- int activateTimers();
-};
-
struct QSockNot
{
QSocketNotifier *obj;
diff --git a/src/corelib/kernel/qtimerinfo_unix.cpp b/src/corelib/kernel/qtimerinfo_unix.cpp
new file mode 100644
index 0000000000..0bb61de02e
--- /dev/null
+++ b/src/corelib/kernel/qtimerinfo_unix.cpp
@@ -0,0 +1,376 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qelapsedtimer.h>
+#include <qcoreapplication.h>
+
+#include "private/qcore_unix_p.h"
+#include "private/qtimerinfo_unix_p.h"
+#include "private/qobject_p.h"
+#include "private/qabstracteventdispatcher_p.h"
+
+#include <sys/times.h>
+
+QT_BEGIN_NAMESPACE
+
+Q_CORE_EXPORT bool qt_disable_lowpriority_timers=false;
+
+/*
+ * Internal functions for manipulating timer data structures. The
+ * timerBitVec array is used for keeping track of timer identifiers.
+ */
+
+QTimerInfoList::QTimerInfoList()
+{
+#if (_POSIX_MONOTONIC_CLOCK-0 <= 0) && !defined(Q_OS_MAC) && !defined(Q_OS_NACL)
+ if (!QElapsedTimer::isMonotonic()) {
+ // not using monotonic timers, initialize the timeChanged() machinery
+ previousTime = qt_gettime();
+
+ tms unused;
+ previousTicks = times(&unused);
+
+ ticksPerSecond = sysconf(_SC_CLK_TCK);
+ msPerTick = 1000/ticksPerSecond;
+ } else {
+ // detected monotonic timers
+ previousTime.tv_sec = previousTime.tv_usec = 0;
+ previousTicks = 0;
+ ticksPerSecond = 0;
+ msPerTick = 0;
+ }
+#endif
+
+ firstTimerInfo = 0;
+}
+
+timeval QTimerInfoList::updateCurrentTime()
+{
+ return (currentTime = qt_gettime());
+}
+
+#if ((_POSIX_MONOTONIC_CLOCK-0 <= 0) && !defined(Q_OS_MAC) && !defined(Q_OS_INTEGRITY)) || defined(QT_BOOTSTRAPPED)
+
+template <>
+timeval qAbs(const timeval &t)
+{
+ timeval tmp = t;
+ if (tmp.tv_sec < 0) {
+ tmp.tv_sec = -tmp.tv_sec - 1;
+ tmp.tv_usec -= 1000000;
+ }
+ if (tmp.tv_sec == 0 && tmp.tv_usec < 0) {
+ tmp.tv_usec = -tmp.tv_usec;
+ }
+ return normalizedTimeval(tmp);
+}
+
+/*
+ Returns true if the real time clock has changed by more than 10%
+ relative to the processor time since the last time this function was
+ called. This presumably means that the system time has been changed.
+
+ If /a delta is nonzero, delta is set to our best guess at how much the system clock was changed.
+*/
+bool QTimerInfoList::timeChanged(timeval *delta)
+{
+#ifdef Q_OS_NACL
+ Q_UNUSED(delta)
+ return false; // Calling "times" crashes.
+#endif
+ struct tms unused;
+ clock_t currentTicks = times(&unused);
+
+ clock_t elapsedTicks = currentTicks - previousTicks;
+ timeval elapsedTime = currentTime - previousTime;
+
+ timeval elapsedTimeTicks;
+ elapsedTimeTicks.tv_sec = elapsedTicks / ticksPerSecond;
+ elapsedTimeTicks.tv_usec = (((elapsedTicks * 1000) / ticksPerSecond) % 1000) * 1000;
+
+ timeval dummy;
+ if (!delta)
+ delta = &dummy;
+ *delta = elapsedTime - elapsedTimeTicks;
+
+ previousTicks = currentTicks;
+ previousTime = currentTime;
+
+ // If tick drift is more than 10% off compared to realtime, we assume that the clock has
+ // been set. Of course, we have to allow for the tick granularity as well.
+ timeval tickGranularity;
+ tickGranularity.tv_sec = 0;
+ tickGranularity.tv_usec = msPerTick * 1000;
+ return elapsedTimeTicks < ((qAbs(*delta) - tickGranularity) * 10);
+}
+
+void QTimerInfoList::repairTimersIfNeeded()
+{
+ if (QElapsedTimer::isMonotonic())
+ return;
+ timeval delta;
+ if (timeChanged(&delta))
+ timerRepair(delta);
+}
+
+#else // !(_POSIX_MONOTONIC_CLOCK-0 <= 0) && !defined(QT_BOOTSTRAPPED)
+
+void QTimerInfoList::repairTimersIfNeeded()
+{
+}
+
+#endif
+
+/*
+ insert timer info into list
+*/
+void QTimerInfoList::timerInsert(QTimerInfo *ti)
+{
+ int index = size();
+ while (index--) {
+ register const QTimerInfo * const t = at(index);
+ if (!(ti->timeout < t->timeout))
+ break;
+ }
+ insert(index+1, ti);
+}
+
+/*
+ repair broken timer
+*/
+void QTimerInfoList::timerRepair(const timeval &diff)
+{
+ // repair all timers
+ for (int i = 0; i < size(); ++i) {
+ register QTimerInfo *t = at(i);
+ t->timeout = t->timeout + diff;
+ }
+}
+
+static timeval roundToMillisecond(timeval val)
+{
+ // always round up
+ // worst case scenario is that the first trigger of a 1-ms timer is 0.999 ms late
+
+ int us = val.tv_usec % 1000;
+ val.tv_usec += 1000 - us;
+ return normalizedTimeval(val);
+}
+
+/*
+ Returns the time to wait for the next timer, or null if no timers
+ are waiting.
+*/
+bool QTimerInfoList::timerWait(timeval &tm)
+{
+ timeval currentTime = updateCurrentTime();
+ repairTimersIfNeeded();
+
+ // Find first waiting timer not already active
+ QTimerInfo *t = 0;
+ for (QTimerInfoList::const_iterator it = constBegin(); it != constEnd(); ++it) {
+ if (!(*it)->activateRef) {
+ t = *it;
+ break;
+ }
+ }
+
+ if (!t)
+ return false;
+
+ if (currentTime < t->timeout) {
+ // time to wait
+ tm = roundToMillisecond(t->timeout - currentTime);
+ } else {
+ // no time to wait
+ tm.tv_sec = 0;
+ tm.tv_usec = 0;
+ }
+
+ return true;
+}
+
+void QTimerInfoList::registerTimer(int timerId, int interval, QObject *object)
+{
+ QTimerInfo *t = new QTimerInfo;
+ t->id = timerId;
+ t->interval.tv_sec = interval / 1000;
+ t->interval.tv_usec = (interval % 1000) * 1000;
+ t->timeout = updateCurrentTime() + t->interval;
+ t->obj = object;
+ t->activateRef = 0;
+
+ timerInsert(t);
+}
+
+bool QTimerInfoList::unregisterTimer(int timerId)
+{
+ // set timer inactive
+ for (int i = 0; i < count(); ++i) {
+ register QTimerInfo *t = at(i);
+ if (t->id == timerId) {
+ // found it
+ removeAt(i);
+ if (t == firstTimerInfo)
+ firstTimerInfo = 0;
+ if (t->activateRef)
+ *(t->activateRef) = 0;
+
+ // release the timer id
+ if (!QObjectPrivate::get(t->obj)->inThreadChangeEvent)
+ QAbstractEventDispatcherPrivate::releaseTimerId(timerId);
+
+ delete t;
+ return true;
+ }
+ }
+ // id not found
+ return false;
+}
+
+bool QTimerInfoList::unregisterTimers(QObject *object)
+{
+ if (isEmpty())
+ return false;
+ for (int i = 0; i < count(); ++i) {
+ register QTimerInfo *t = at(i);
+ if (t->obj == object) {
+ // object found
+ removeAt(i);
+ if (t == firstTimerInfo)
+ firstTimerInfo = 0;
+ if (t->activateRef)
+ *(t->activateRef) = 0;
+
+ // release the timer id
+ if (!QObjectPrivate::get(t->obj)->inThreadChangeEvent)
+ QAbstractEventDispatcherPrivate::releaseTimerId(t->id);
+
+ delete t;
+ // move back one so that we don't skip the new current item
+ --i;
+ }
+ }
+ return true;
+}
+
+QList<QPair<int, int> > QTimerInfoList::registeredTimers(QObject *object) const
+{
+ QList<QPair<int, int> > list;
+ for (int i = 0; i < count(); ++i) {
+ register const QTimerInfo * const t = at(i);
+ if (t->obj == object)
+ list << QPair<int, int>(t->id, t->interval.tv_sec * 1000 + t->interval.tv_usec / 1000);
+ }
+ return list;
+}
+
+/*
+ Activate pending timers, returning how many where activated.
+*/
+int QTimerInfoList::activateTimers()
+{
+ if (qt_disable_lowpriority_timers || isEmpty())
+ return 0; // nothing to do
+
+ int n_act = 0, maxCount = 0;
+ firstTimerInfo = 0;
+
+ timeval currentTime = updateCurrentTime();
+ repairTimersIfNeeded();
+
+
+ // Find out how many timer have expired
+ for (QTimerInfoList::const_iterator it = constBegin(); it != constEnd(); ++it) {
+ if (currentTime < (*it)->timeout)
+ break;
+ maxCount++;
+ }
+
+ //fire the timers.
+ while (maxCount--) {
+ if (isEmpty())
+ break;
+
+ QTimerInfo *currentTimerInfo = first();
+ if (currentTime < currentTimerInfo->timeout)
+ break; // no timer has expired
+
+ if (!firstTimerInfo) {
+ firstTimerInfo = currentTimerInfo;
+ } else if (firstTimerInfo == currentTimerInfo) {
+ // avoid sending the same timer multiple times
+ break;
+ } else if (currentTimerInfo->interval < firstTimerInfo->interval
+ || currentTimerInfo->interval == firstTimerInfo->interval) {
+ firstTimerInfo = currentTimerInfo;
+ }
+
+ // remove from list
+ removeFirst();
+
+ // determine next timeout time
+ currentTimerInfo->timeout += currentTimerInfo->interval;
+ if (currentTimerInfo->timeout < currentTime)
+ currentTimerInfo->timeout = currentTime + currentTimerInfo->interval;
+
+ // reinsert timer
+ timerInsert(currentTimerInfo);
+ if (currentTimerInfo->interval.tv_usec > 0 || currentTimerInfo->interval.tv_sec > 0)
+ n_act++;
+
+ if (!currentTimerInfo->activateRef) {
+ // send event, but don't allow it to recurse
+ currentTimerInfo->activateRef = &currentTimerInfo;
+
+ QTimerEvent e(currentTimerInfo->id);
+ QCoreApplication::sendEvent(currentTimerInfo->obj, &e);
+
+ if (currentTimerInfo)
+ currentTimerInfo->activateRef = 0;
+ }
+ }
+
+ firstTimerInfo = 0;
+ return n_act;
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qtimerinfo_unix_p.h b/src/corelib/kernel/qtimerinfo_unix_p.h
new file mode 100644
index 0000000000..d464a146e3
--- /dev/null
+++ b/src/corelib/kernel/qtimerinfo_unix_p.h
@@ -0,0 +1,110 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTIMERINFO_UNIX_P_H
+#define QTIMERINFO_UNIX_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <qobject.h>
+#include <qlist.h>
+#include <qpair.h>
+
+#include <sys/time.h> // struct timeval
+
+QT_BEGIN_NAMESPACE
+
+// internal timer info
+struct QTimerInfo {
+ int id; // - timer identifier
+ timeval interval; // - timer interval
+ timeval timeout; // - when to sent event
+ QObject *obj; // - object to receive event
+ QTimerInfo **activateRef; // - ref from activateTimers
+};
+
+class QTimerInfoList : public QList<QTimerInfo*>
+{
+#if ((_POSIX_MONOTONIC_CLOCK-0 <= 0) && !defined(Q_OS_MAC)) || defined(QT_BOOTSTRAPPED)
+ timeval previousTime;
+ clock_t previousTicks;
+ int ticksPerSecond;
+ int msPerTick;
+
+ bool timeChanged(timeval *delta);
+#endif
+
+ // state variables used by activateTimers()
+ QTimerInfo *firstTimerInfo;
+
+public:
+ QTimerInfoList();
+
+ timeval currentTime;
+ timeval updateCurrentTime();
+
+ // must call updateCurrentTime() first!
+ void repairTimersIfNeeded();
+
+ bool timerWait(timeval &);
+ void timerInsert(QTimerInfo *);
+ void timerRepair(const timeval &);
+
+ void registerTimer(int timerId, int interval, QObject *object);
+ bool unregisterTimer(int timerId);
+ bool unregisterTimers(QObject *object);
+ QList<QPair<int, int> > registeredTimers(QObject *object) const;
+
+ int activateTimers();
+};
+
+QT_END_NAMESPACE
+
+#endif // QTIMERINFO_UNIX_P_H