qt-ble: improve responsiveness of waiting for bluetooth data

Our model of waiting for 100ms before re-checking if we got a packet
over BLE resulted in potentially horrendously bad latency for received
packets.

That isn't just a possible performance issue, it actually seems to cause
IO errors with my Suunto EON Core.  I'm not entirely sure why, but it
might simply be some timing interaction, particularly since the IO
errors seemed to primarily happen when the dive computer itself was also
busy updating the screen (ie if you pressed buttons on the dive computer
to switch to compass mode, for example).

So replace the silly hardcoded 100ms "waitFor()" function with a
WAITFOR() macro that checks the provided expression every time through
the loop, which gets us a much lower latency (we basically check every
ten milliseconds).

The macro is not beautiful, but it WorksForMe(tm).

This makes a huge difference to the reliability of the download for me,
and might matter for some other dive computers too.

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
Linus Torvalds 2018-06-20 15:03:57 +09:00 committed by Dirk Hohndel
parent b75eae95c1
commit 21d6531e45

View file

@ -29,17 +29,26 @@ static int debugCounter;
#define MAXIMAL_HW_CREDIT 255
#define MINIMAL_HW_CREDIT 32
static void waitFor(int ms) {
Q_ASSERT(QCoreApplication::instance());
Q_ASSERT(QThread::currentThread());
#define WAITFOR(expression, ms) do { \
Q_ASSERT(QCoreApplication::instance()); \
Q_ASSERT(QThread::currentThread()); \
\
if (expression) \
break; \
QElapsedTimer timer; \
timer.start(); \
\
do { \
QCoreApplication::processEvents(QEventLoop::AllEvents, ms); \
if (expression) \
break; \
QThread::msleep(10); \
} while (timer.elapsed() < (ms)); \
} while (0)
QElapsedTimer timer;
timer.start();
do {
QCoreApplication::processEvents(QEventLoop::AllEvents, ms);
QThread::msleep(10);
} while (timer.elapsed() < ms);
static void waitFor(int ms)
{
WAITFOR(false, ms);
}
extern "C" {
@ -176,17 +185,11 @@ dc_status_t BLEObject::read(void *data, size_t size, size_t *actual)
if (list.isEmpty())
return DC_STATUS_IO;
int msec = BLE_TIMEOUT;
while (msec > 0 && receivedPackets.isEmpty()) {
waitFor(100);
msec -= 100;
}
WAITFOR(!receivedPackets.isEmpty(), BLE_TIMEOUT);
if (receivedPackets.isEmpty())
return DC_STATUS_IO;
}
// Still no packet?
if (receivedPackets.isEmpty())
return DC_STATUS_IO;
QByteArray packet = receivedPackets.takeFirst();
if ((size_t)packet.size() > size)