summaryrefslogtreecommitdiffstats
path: root/src/corelib/kernel
diff options
context:
space:
mode:
authorSean Harmer <sean.harmer@kdab.com>2012-08-28 15:33:51 +0100
committerThe Qt Project <gerrit-noreply@qt-project.org>2012-10-12 02:19:36 +0200
commit23a0d7f1235e09875e8ca067758b40a9df4669a5 (patch)
tree63ac395543232be20c9230fb557320046c33efda /src/corelib/kernel
parent94f67af01db287e67fce09cdb56a9f1d283f8b64 (diff)
QNX: Remove the busy loop work around for bps ignoring timeout bug
This is a backport of qtbase commit b72904e8540e4aa1f1396893f5d1b216d745cdc3 Change-Id: I7489dc69fa505e76f707531e70a8011d596da19d Reviewed-by: Thomas McGuire <thomas.mcguire@kdab.com> Reviewed-by: Kevin Krammer <kevin.krammer@kdab.com>
Diffstat (limited to 'src/corelib/kernel')
-rw-r--r--src/corelib/kernel/qeventdispatcher_blackberry.cpp62
1 files changed, 41 insertions, 21 deletions
diff --git a/src/corelib/kernel/qeventdispatcher_blackberry.cpp b/src/corelib/kernel/qeventdispatcher_blackberry.cpp
index 9d874bd3bc..921dfdb14b 100644
--- a/src/corelib/kernel/qeventdispatcher_blackberry.cpp
+++ b/src/corelib/kernel/qeventdispatcher_blackberry.cpp
@@ -242,11 +242,28 @@ void QEventDispatcherBlackberry::unregisterSocketNotifier(QSocketNotifier *notif
}
}
+static inline bool updateTimeout(int *timeout, const struct timeval &start)
+{
+ if (Q_UNLIKELY(!QElapsedTimer::isMonotonic())) {
+ // we cannot recalculate the timeout without a monotonic clock as the time may have changed
+ return false;
+ }
+
+ // clock source is monotonic, so we can recalculate how much timeout is left
+ timeval t2 = qt_gettime();
+ int elapsed = (t2.tv_sec * 1000 + t2.tv_usec / 1000) - (start.tv_sec * 1000 + start.tv_usec / 1000);
+ *timeout -= elapsed;
+ return *timeout >= 0;
+}
+
int QEventDispatcherBlackberry::select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
timeval *timeout)
{
Q_UNUSED(nfds);
+ // Make a note of the start time
+ timeval startTime = qt_gettime();
+
// prepare file sets for bps callback
Q_D(QEventDispatcherBlackberry);
d->ioData->count = 0;
@@ -280,36 +297,39 @@ int QEventDispatcherBlackberry::select(int nfds, fd_set *readfds, fd_set *writef
if (exceptfds)
FD_ZERO(exceptfds);
- // convert timeout to milliseconds
- int timeout_ms = -1;
+ // Convert timeout to milliseconds
+ int timeout_bps = -1;
if (timeout)
- timeout_ms = (timeout->tv_sec * 1000) + (timeout->tv_usec / 1000);
+ timeout_bps = (timeout->tv_sec * 1000) + (timeout->tv_usec / 1000);
- QElapsedTimer timer;
- timer.start();
-
- do {
- // wait for event or file to be ready
+ // This loop exists such that we can drain the bps event queue of all native events
+ // more efficiently than if we were to return control to Qt after each event. This
+ // is important for handling touch events which can come in rapidly.
+ forever {
+ // Wait for event or file to be ready
bps_event_t *event = NULL;
-
- // \TODO Remove this when bps is fixed
- // BPS has problems respecting timeouts.
- // Replace the bps_get_event statement
- // with the following commented version
- // once bps is fixed.
- // result = bps_get_event(&event, timeout_ms);
- result = bps_get_event(&event, 0);
+ result = bps_get_event(&event, timeout_bps);
if (result != BPS_SUCCESS)
qWarning("QEventDispatcherBlackberry::select: bps_get_event() failed");
- if (!event)
+ // In the case of !event, we break out of the loop to let Qt process the timers
+ // that are now ready (since timeout has expired).
+ // In the case of bpsIOReadyDomain, we break out to let Qt process the FDs that
+ // are ready. If we do not do this activation of QSocketNotifiers etc would be
+ // delayed.
+ if (!event || bps_event_get_domain(event) == bpsIOReadyDomain)
break;
- // pass all received events through filter - except IO ready events
- if (event && bps_event_get_domain(event) != bpsIOReadyDomain)
- filterEvent((void*)event);
- } while (timer.elapsed() < timeout_ms);
+ // Any other events must be bps native events so we pass all such received
+ // events through the native event filter chain
+ filterEvent((void*)event);
+
+ // Update the timeout. If this fails we have exceeded our alloted time or the system
+ // clock has changed time and we cannot calculate a new timeout so we bail out.
+ if (!updateTimeout(&timeout_bps, startTime))
+ break;
+ }
// \TODO Remove this when bps is fixed (see comment above)
result = bps_remove_fd(d->thread_pipe[0]);