summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBernd Weimer <bweimer@rim.com>2012-10-19 08:43:32 (GMT)
committerThe Qt Project <gerrit-noreply@qt-project.org>2012-10-30 16:35:27 (GMT)
commit7301665b57745a0b6d7b551834d603c6aa275b8c (patch)
tree45c166d8ee72c0214c03fbff03d8221149adc88b
parent2d487381e8537024bbb10b03d324cea6b6060185 (diff)
downloadQt-7301665b57745a0b6d7b551834d603c6aa275b8c.zip
Qt-7301665b57745a0b6d7b551834d603c6aa275b8c.tar.gz
Qt-7301665b57745a0b6d7b551834d603c6aa275b8c.tar.bz2
Blackberry: Fix for slowness of touch move events
In the event dispatcher native events will be processed in a tight loop to drain the queue. IO events and timers will be postponed. Backported from c4b2d77f40a42a67480bb49aa63b0953c80c024a Change-Id: Iaf408425000e7fd6fdbf0992bbf927d03a650581 Reviewed-by: Thomas McGuire <thomas.mcguire@kdab.com> Reviewed-by: Kevin Krammer <kevin.krammer@kdab.com> Reviewed-by: Sean Harmer <sean.harmer@kdab.com> Reviewed-by: Rafael Roquetto <rafael.roquetto@kdab.com>
-rw-r--r--src/corelib/kernel/qeventdispatcher_blackberry.cpp106
1 files changed, 46 insertions, 60 deletions
diff --git a/src/corelib/kernel/qeventdispatcher_blackberry.cpp b/src/corelib/kernel/qeventdispatcher_blackberry.cpp
index 3c00e91..366bacb 100644
--- a/src/corelib/kernel/qeventdispatcher_blackberry.cpp
+++ b/src/corelib/kernel/qeventdispatcher_blackberry.cpp
@@ -43,7 +43,6 @@
#include "qsocketnotifier.h"
#include "qdebug.h"
#include "qelapsedtimer.h"
-#include "qthread.h"
#include <bps/bps.h>
#include <bps/event.h>
@@ -244,28 +243,6 @@ void QEventDispatcherBlackberry::unregisterSocketNotifier(QSocketNotifier *notif
}
}
-static inline bool updateTimeout(int *timeout, const struct timeval &start)
-{
- // A timeout of -1 means we should block indefinitely. If we get here, we got woken up by a
- // non-IO BPS event, and that event has been processed already. This means we can go back and
- // block in bps_get_event().
- // Note that processing the BPS event might have triggered a wakeup, in that case we get a
- // IO event in the next bps_get_event() right away.
- if (*timeout == -1)
- return true;
-
- 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)
{
@@ -292,63 +269,72 @@ int QEventDispatcherBlackberry::select(int nfds, fd_set *readfds, fd_set *writef
FD_ZERO(exceptfds);
// Convert timeout to milliseconds
- int timeout_bps = -1;
+ int timeoutTotal = -1;
if (timeout)
- timeout_bps = (timeout->tv_sec * 1000) + (timeout->tv_usec / 1000);
+ timeoutTotal = (timeout->tv_sec * 1000) + (timeout->tv_usec / 1000);
+
+ int timeoutLeft = timeoutTotal;
- bool hasProcessedEventsOnce = false;
bps_event_t *event = 0;
+ unsigned int eventCount = 0;
// 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 {
- Q_ASSERT(!hasProcessedEventsOnce || event);
-
- // Only emit the awake() and aboutToBlock() signals in the second iteration. For the first
- // iteration, the UNIX event dispatcher will have taken care of that already.
- if (hasProcessedEventsOnce)
- emit awake();
-
- // Filtering the native event should happen between the awake() and aboutToBlock() signal
- // emissions. The calls awake() - filterNativeEvent() - aboutToBlock() - bps_get_event()
- // need not to be interrupted by a break or return statement.
- //
- // Because of this, the native event is actually processed one loop iteration
- // after it was retrieved with bps_get_event().
- if (event)
- filterEvent((void*)event);
-
- if (hasProcessedEventsOnce)
- emit aboutToBlock();
+ // Only emit the awake() and aboutToBlock() signals in the second iteration. For the
+ // first iteration, the UNIX event dispatcher will have taken care of that already.
+ // Also native events are actually processed one loop iteration after they were
+ // retrieved with bps_get_event().
+
+ // Filtering the native event should happen between the awake() and aboutToBlock()
+ // signal emissions. The calls awake() - filterNativeEvent() - aboutToBlock() -
+ // bps_get_event() need not to be interrupted by a break or return statement.
+ if (eventCount > 0) {
+ if (event) {
+ emit awake();
+ filterEvent(static_cast<void*>(event));
+ emit aboutToBlock();
+ }
+
+ // Update the timeout
+ // Clock source is monotonic, so we can recalculate how much timeout is left
+ if (timeoutTotal != -1) {
+ timeval t2 = qt_gettime();
+ timeoutLeft = timeoutTotal - ((t2.tv_sec * 1000 + t2.tv_usec / 1000)
+ - (startTime.tv_sec * 1000 + startTime.tv_usec / 1000));
+ if (timeoutLeft < 0)
+ timeoutLeft = 0;
+ }
+ }
// Wait for event or file to be ready
event = 0;
- const int result = bps_get_event(&event, timeout_bps);
+ const int result = bps_get_event(&event, timeoutLeft);
if (result != BPS_SUCCESS)
qWarning("QEventDispatcherBlackberry::select: bps_get_event() failed");
- // 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;
+ if (!event) // In case of !event, we break out of the loop to let Qt process the timers
+ break; // (since timeout has expired) and socket notifiers that are now ready.
- // 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)) {
+ if (bps_event_get_domain(event) == bpsIOReadyDomain) {
+ timeoutTotal = 0; // in order to immediately drain the event queue of native events
+ event = 0; // (especially touch move events) we don't break out here
+ }
- // No more loop iteration, so we need to filter the event here.
- filterEvent((void*)event);
+ ++eventCount;
+
+ // Make sure we are not trapped in this loop due to continuous native events
+ // also we cannot recalculate the timeout without a monotonic clock as the time may have changed
+ const unsigned int maximumEventCount = 12;
+ if (Q_UNLIKELY((eventCount > maximumEventCount && timeoutLeft == 0)
+ || !QElapsedTimer::isMonotonic())) {
+ if (event)
+ filterEvent(static_cast<void*>(event));
break;
}
-
- hasProcessedEventsOnce = true;
}
-
// the number of bits set in the file sets
return d->ioData->count;
}