From 2095658e2c850e7f355c1bd1f5ee33e3a5b961f5 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint <Friedemann.Kleint@nokia.com> Date: Fri, 21 Aug 2009 10:29:48 +0200 Subject: [PATCH] Trk: Factor out write queue using a functor. --- tests/manual/trk/launcher.cpp | 180 +++++-------------------------- tests/manual/trk/launcher.h | 16 --- tests/manual/trk/trkdevice.cpp | 176 +++++++++++++++++++++++++++++- tests/manual/trk/trkdevice.h | 54 +++++++++- tests/manual/trk/trkfunctor.h | 144 +++++++++++++++++++++++++ tests/manual/trk/trklauncher.pri | 1 + 6 files changed, 398 insertions(+), 173 deletions(-) create mode 100644 tests/manual/trk/trkfunctor.h diff --git a/tests/manual/trk/launcher.cpp b/tests/manual/trk/launcher.cpp index 6e3a68ee3f3..a3d3d06e035 100644 --- a/tests/manual/trk/launcher.cpp +++ b/tests/manual/trk/launcher.cpp @@ -40,32 +40,18 @@ namespace trk { -struct TrkMessage { - TrkMessage() { code = token = 0; callBack = 0; } - byte code; - byte token; - QByteArray data; - QVariant cookie; - Launcher::TrkCallBack callBack; -}; +typedef TrkWriteQueueDevice::Callback Callback; struct LauncherPrivate { LauncherPrivate(); - TrkDevice m_device; + TrkWriteQueueDevice m_device; QString m_trkServerName; QByteArray m_trkReadBuffer; - unsigned char m_trkWriteToken; - QQueue<TrkMessage> m_trkWriteQueue; - QHash<byte, TrkMessage> m_writtenTrkMessages; - QByteArray m_trkReadQueue; - bool m_trkWriteBusy; - void logMessage(const QString &msg); // Debuggee state Session m_session; // global-ish data (process id, target information) - int m_timerId; QString m_fileName; QString m_copySrcFileName; QString m_copyDstFileName; @@ -74,15 +60,10 @@ struct LauncherPrivate { }; LauncherPrivate::LauncherPrivate() : - m_trkWriteToken(0), - m_trkWriteBusy(false), - m_timerId(-1), m_verbose(0) { } -#define CB(s) &Launcher::s - Launcher::Launcher() : d(new LauncherPrivate) { @@ -135,12 +116,11 @@ bool Launcher::startServer(QString *errorMessage) } if (!d->m_device.open(d->m_trkServerName, errorMessage)) return false; - d->m_timerId = startTimer(100); - sendTrkInitialPing(); - sendTrkMessage(TrkConnect); // Connect - sendTrkMessage(TrkSupported, CB(handleSupportMask)); - sendTrkMessage(TrkCpuType, CB(handleCpuType)); - sendTrkMessage(TrkVersions, CB(handleTrkVersion)); + d->m_device.sendTrkInitialPing(); + d->m_device.sendTrkMessage(TrkConnect); // Connect + d->m_device.sendTrkMessage(TrkSupported, Callback(this, &Launcher::handleSupportMask)); + d->m_device.sendTrkMessage(TrkCpuType, Callback(this, &Launcher::handleCpuType)); + d->m_device.sendTrkMessage(TrkVersions, Callback(this, &Launcher::handleTrkVersion)); if (d->m_fileName.isEmpty()) return true; if (!d->m_copySrcFileName.isEmpty() && !d->m_copyDstFileName.isEmpty()) @@ -170,45 +150,10 @@ void Launcher::logMessage(const QString &msg) qDebug() << "ADAPTER: " << qPrintable(msg); } -void Launcher::timerEvent(QTimerEvent *) -{ - if (d->m_verbose>1) - qDebug("."); - tryTrkWrite(); -} - -byte Launcher::nextTrkWriteToken() -{ - ++d->m_trkWriteToken; - if (d->m_trkWriteToken == 0) - ++d->m_trkWriteToken; - return d->m_trkWriteToken; -} - -void Launcher::sendTrkMessage(byte code, TrkCallBack callBack, - const QByteArray &data, const QVariant &cookie) -{ - TrkMessage msg; - msg.code = code; - msg.token = nextTrkWriteToken(); - msg.callBack = callBack; - msg.data = data; - msg.cookie = cookie; - queueTrkMessage(msg); -} - -void Launcher::sendTrkInitialPing() -{ - TrkMessage msg; - msg.code = 0x00; // Ping - msg.token = 0; // reset sequence count - queueTrkMessage(msg); -} - void Launcher::waitForTrkFinished(const TrkResult &result) { Q_UNUSED(result) - sendTrkMessage(TrkPing, CB(handleWaitForFinished)); + d->m_device.sendTrkMessage(TrkPing, Callback(this, &Launcher::handleWaitForFinished)); } void Launcher::terminate() @@ -216,57 +161,11 @@ void Launcher::terminate() QByteArray ba; appendShort(&ba, 0x0000, TargetByteOrder); appendInt(&ba, d->m_session.pid, TargetByteOrder); - sendTrkMessage(TrkDeleteItem, CB(waitForTrkFinished), ba); -} - -void Launcher::sendTrkAck(byte token) -{ - logMessage(QString("SENDING ACKNOWLEDGEMENT FOR TOKEN %1").arg(int(token))); - TrkMessage msg; - msg.code = 0x80; - msg.token = token; - msg.data.append('\0'); - // The acknowledgement must not be queued! - //queueMessage(msg); - trkWriteRawMessage(msg); - // 01 90 00 07 7e 80 01 00 7d 5e 7e -} - -void Launcher::queueTrkMessage(const TrkMessage &msg) -{ - d->m_trkWriteQueue.append(msg); -} - -void Launcher::tryTrkWrite() -{ - if (d->m_trkWriteBusy) - return; - if (d->m_trkWriteQueue.isEmpty()) - return; - - TrkMessage msg = d->m_trkWriteQueue.dequeue(); - trkWrite(msg); -} - -void Launcher::trkWriteRawMessage(const TrkMessage &msg) -{ - const QByteArray ba = frameMessage(msg.code, msg.token, msg.data, serialFrame()); - logMessage("WRITE: " + stringFromArray(ba)); - QString errorMessage; - if (!d->m_device.write(ba, &errorMessage)) - logMessage(errorMessage); -} - -void Launcher::trkWrite(const TrkMessage &msg) -{ - d->m_writtenTrkMessages.insert(msg.token, msg); - d->m_trkWriteBusy = true; - trkWriteRawMessage(msg); + d->m_device.sendTrkMessage(TrkDeleteItem, Callback(this, &Launcher::waitForTrkFinished), ba); } void Launcher::handleResult(const TrkResult &result) { - d->m_trkWriteBusy = false; QByteArray prefix = "READ BUF: "; QByteArray str = result.toString().toUtf8(); if (result.isDebugOutput) { // handle application output @@ -275,28 +174,8 @@ void Launcher::handleResult(const TrkResult &result) return; } switch (result.code) { - case TrkNotifyAck: { // ACK - //logMessage(prefix + "ACK: " + str); - if (!result.data.isEmpty() && result.data.at(0)) - logMessage(prefix + "ERR: " +QByteArray::number(result.data.at(0))); - //logMessage("READ RESULT FOR TOKEN: " << token); - if (!d->m_writtenTrkMessages.contains(result.token)) { - logMessage("NO ENTRY FOUND!"); - } - TrkMessage msg = d->m_writtenTrkMessages.take(result.token); - TrkResult result1 = result; - result1.cookie = msg.cookie; - TrkCallBack cb = msg.callBack; - if (cb) { - //logMessage("HANDLE: " << stringFromArray(result.data)); - (this->*cb)(result1); - } else { - QString msg = result.cookie.toString(); - if (!msg.isEmpty()) - logMessage("HANDLE: " + msg + stringFromArray(result.data)); - } + case TrkNotifyAck: break; - } case TrkNotifyNak: { // NAK logMessage(prefix + "NAK: " + str); //logMessage(prefix << "TOKEN: " << result.token); @@ -311,17 +190,17 @@ void Launcher::handleResult(const TrkResult &result) // uint pid = extractInt(data + 4); // ProcessID: 4 bytes; // uint tid = extractInt(data + 8); // ThreadID: 4 bytes //logMessage(prefix << " ADDR: " << addr << " PID: " << pid << " TID: " << tid); - sendTrkAck(result.token); + d->m_device.sendTrkAck(result.token); break; } case TrkNotifyException: { // Notify Exception (obsolete) logMessage(prefix + "NOTE: EXCEPTION " + str); - sendTrkAck(result.token); + d->m_device.sendTrkAck(result.token); break; } case TrkNotifyInternalError: { // logMessage(prefix + "NOTE: INTERNAL ERROR: " + str); - sendTrkAck(result.token); + d->m_device.sendTrkAck(result.token); break; } @@ -353,8 +232,8 @@ void Launcher::handleResult(const TrkResult &result) QByteArray ba; appendInt(&ba, d->m_session.pid); appendInt(&ba, d->m_session.tid); - sendTrkMessage(TrkContinue, 0, ba, "CONTINUE"); - //sendTrkAck(result.token) + d->m_device.sendTrkMessage(TrkContinue, Callback(), ba, "CONTINUE"); + //d->m_device.sendTrkAck(result.token) break; } case TrkNotifyDeleted: { // NotifyDeleted @@ -364,25 +243,25 @@ void Launcher::handleResult(const TrkResult &result) logMessage(QString::fromLatin1("%1 %2 UNLOAD: %3"). arg(QString::fromAscii(prefix)).arg(itemType ? QLatin1String("LIB") : QLatin1String("PROCESS")). arg(name)); - sendTrkAck(result.token); + d->m_device.sendTrkAck(result.token); if (itemType == 0) { // process - sendTrkMessage(TrkDisconnect, CB(waitForTrkFinished)); + d->m_device.sendTrkMessage(TrkDisconnect, Callback(this, &Launcher::waitForTrkFinished)); } break; } case TrkNotifyProcessorStarted: { // NotifyProcessorStarted logMessage(prefix + "NOTE: PROCESSOR STARTED: " + str); - sendTrkAck(result.token); + d->m_device.sendTrkAck(result.token); break; } case TrkNotifyProcessorStandBy: { // NotifyProcessorStandby logMessage(prefix + "NOTE: PROCESSOR STANDBY: " + str); - sendTrkAck(result.token); + d->m_device.sendTrkAck(result.token); break; } case TrkNotifyProcessorReset: { // NotifyProcessorReset logMessage(prefix + "NOTE: PROCESSOR RESET: " + str); - sendTrkAck(result.token); + d->m_device.sendTrkAck(result.token); break; } default: { @@ -409,7 +288,7 @@ void Launcher::handleTrkVersion(const TrkResult &result) << " float size: " << d->m_session.fpTypeSize << " Trk: v" << trkMajor << '.' << trkMinor << " Protocol: " << protocolMajor << '.' << protocolMinor; qWarning("%s", qPrintable(msg)); - sendTrkMessage(TrkPing, CB(waitForTrkFinished)); + d->m_device.sendTrkMessage(TrkPing, Callback(this, &Launcher::waitForTrkFinished)); } } @@ -429,13 +308,13 @@ void Launcher::handleFileCreation(const TrkResult &result) QByteArray ba; appendInt(&ba, copyFileHandle, TargetByteOrder); appendString(&ba, src.mid(pos, BLOCKSIZE), TargetByteOrder, false); - sendTrkMessage(TrkWriteFile, 0, ba); + d->m_device.sendTrkMessage(TrkWriteFile, Callback(), ba); pos += BLOCKSIZE; } QByteArray ba; appendInt(&ba, copyFileHandle, TargetByteOrder); appendInt(&ba, QDateTime::currentDateTime().toTime_t(), TargetByteOrder); - sendTrkMessage(TrkCloseFile, CB(handleFileCreated), ba); + d->m_device.sendTrkMessage(TrkCloseFile, Callback(this, &Launcher::handleFileCreated), ba); } void Launcher::handleFileCreated(const TrkResult &result) @@ -480,13 +359,12 @@ void Launcher::handleCreateProcess(const TrkResult &result) QByteArray ba; appendInt(&ba, d->m_session.pid); appendInt(&ba, d->m_session.tid); - sendTrkMessage(TrkContinue, 0, ba, "CONTINUE"); + d->m_device.sendTrkMessage(TrkContinue, Callback(), ba, "CONTINUE"); } void Launcher::handleWaitForFinished(const TrkResult &result) { logMessage(" FINISHED: " + stringFromArray(result.data)); - killTimer(d->m_timerId); emit finished(); } @@ -516,7 +394,7 @@ void Launcher::cleanUp() appendByte(&ba, 0x00); appendByte(&ba, 0x00); appendInt(&ba, d->m_session.pid); - sendTrkMessage(TrkDeleteItem, 0, ba, "Delete process"); + d->m_device.sendTrkMessage(TrkDeleteItem, Callback(), ba, "Delete process"); //---TRK------------------------------------------------------ // Command: 0x80 Acknowledge @@ -552,7 +430,7 @@ void Launcher::cleanUp() //---IDE------------------------------------------------------ // Command: 0x02 Disconnect // [02 27] -// sendTrkMessage(0x02, CB(handleDisconnect)); +// sendTrkMessage(0x02, Callback(this, &Launcher::handleDisconnect)); //---TRK------------------------------------------------------ // Command: 0x80 Acknowledge // Error: 0x00 @@ -564,7 +442,7 @@ void Launcher::copyFileToRemote() QByteArray ba; appendByte(&ba, 0x10); appendString(&ba, d->m_copyDstFileName.toLocal8Bit(), TargetByteOrder, false); - sendTrkMessage(TrkOpenFile, CB(handleFileCreation), ba); + d->m_device.sendTrkMessage(TrkOpenFile, Callback(this, &Launcher::handleFileCreation), ba); } void Launcher::installRemotePackageSilently(const QString &fileName) @@ -573,7 +451,7 @@ void Launcher::installRemotePackageSilently(const QString &fileName) QByteArray ba; appendByte(&ba, 'C'); appendString(&ba, fileName.toLocal8Bit(), TargetByteOrder, false); - sendTrkMessage(TrkInstallFile, CB(handleInstallPackageFinished), ba); + d->m_device.sendTrkMessage(TrkInstallFile, Callback(this, &Launcher::handleInstallPackageFinished), ba); } void Launcher::handleInstallPackageFinished(const TrkResult &) @@ -594,7 +472,7 @@ void Launcher::startInferiorIfNeeded() appendByte(&ba, 0); // ? appendByte(&ba, 0); // ? appendString(&ba, d->m_fileName.toLocal8Bit(), TargetByteOrder); - sendTrkMessage(TrkCreateItem, CB(handleCreateProcess), ba); // Create Item + d->m_device.sendTrkMessage(TrkCreateItem, Callback(this, &Launcher::handleCreateProcess), ba); // Create Item } } diff --git a/tests/manual/trk/launcher.h b/tests/manual/trk/launcher.h index d37aab16bb6..c2527d57d5c 100644 --- a/tests/manual/trk/launcher.h +++ b/tests/manual/trk/launcher.h @@ -70,27 +70,11 @@ private slots: void handleResult(const TrkResult &data); private: - void sendTrkMessage(unsigned char code, - TrkCallBack callBack = 0, - const QByteArray &data = QByteArray(), - const QVariant &cookie = QVariant()); - // adds message to 'send' queue - void queueTrkMessage(const TrkMessage &msg); - void tryTrkWrite(); void tryTrkRead(); - // actually writes a message to the device - void trkWrite(const TrkMessage &msg); - void trkWriteRawMessage(const TrkMessage &msg); - // convienience messages - void sendTrkInitialPing(); - void sendTrkAck(unsigned char token); // kill process and breakpoints void cleanUp(); - void timerEvent(QTimerEvent *ev); - unsigned char nextTrkWriteToken(); - void handleFileCreation(const TrkResult &result); void handleFileCreated(const TrkResult &result); void handleInstallPackageFinished(const TrkResult &result); diff --git a/tests/manual/trk/trkdevice.cpp b/tests/manual/trk/trkdevice.cpp index a045fa41027..13608cb2da8 100644 --- a/tests/manual/trk/trkdevice.cpp +++ b/tests/manual/trk/trkdevice.cpp @@ -32,6 +32,9 @@ #include <QtCore/QString> #include <QtCore/QDebug> +#include <QtCore/QQueue> +#include <QtCore/QHash> +#include <QtCore/QMap> #ifdef Q_OS_WIN # include <windows.h> @@ -194,6 +197,7 @@ void TrkDevice::close() } #ifdef Q_OS_WIN CloseHandle(d->hdevice); + d->hdevice = INVALID_HANDLE_VALUE; #else d->file.close(); #endif @@ -287,8 +291,8 @@ void TrkDevice::tryTrkRead() return; const ushort len = isValidTrkResult(d->trkReadBuffer, d->serialFrame); if (!len) { - d->errorString = QString::fromLatin1("Partial message: %1").arg(stringFromArray(d->trkReadBuffer)); - qWarning("%s\n", qPrintable(d->errorString)); + const QString msg = QString::fromLatin1("Partial message: %1").arg(stringFromArray(d->trkReadBuffer)); + emitError(msg); return; } #else @@ -300,9 +304,9 @@ void TrkDevice::tryTrkRead() const ushort len = isValidTrkResult(d->trkReadBuffer, d->serialFrame); if (!len) { if (d->trkReadBuffer.size() > 10) { - d->errorString = QString::fromLatin1("Unable to extract message from '%1' '%2'"). + const QString msg = QString::fromLatin1("Unable to extract message from '%1' '%2'"). arg(QLatin1String(d->trkReadBuffer.toHex())).arg(QString::fromAscii(d->trkReadBuffer)); - qWarning("%s\n", qPrintable(d->errorString)); + emitError(msg); } return; } @@ -320,4 +324,166 @@ void TrkDevice::timerEvent(QTimerEvent *) tryTrkRead(); } -} // namespace trk +void TrkDevice::emitError(const QString &s) +{ + d->errorString = s; + qWarning("%s\n", qPrintable(s)); + emit error(s); +} + +/* A message to be send to TRK, triggering a callback on receipt + * of the answer. */ +struct TrkMessage { + typedef TrkFunctor1<const TrkResult &> Callback; + + explicit TrkMessage(unsigned char code = 0u, + unsigned char token = 0u, + Callback callback = Callback()); + + unsigned char code; + unsigned char token; + QByteArray data; + QVariant cookie; + Callback callback; + bool invokeOnNAK; +}; + +TrkMessage::TrkMessage(unsigned char c, + unsigned char t, + Callback cb) : + code(c), + token(t), + callback(cb), + invokeOnNAK(false) +{ +} + +// ------- TrkWriteQueueDevice + +struct TrkWriteQueueDevicePrivate { + typedef QMap<unsigned char, TrkMessage> TokenMessageMap; + TrkWriteQueueDevicePrivate(); + + unsigned char trkWriteToken; + QQueue<TrkMessage> trkWriteQueue; + TokenMessageMap writtenTrkMessages; + bool trkWriteBusy; +}; + +TrkWriteQueueDevicePrivate::TrkWriteQueueDevicePrivate() : + trkWriteToken(0), + trkWriteBusy(false) +{ +} + +TrkWriteQueueDevice::TrkWriteQueueDevice(QObject *parent) : + TrkDevice(parent), + qd(new TrkWriteQueueDevicePrivate) +{ + connect(this, SIGNAL(messageReceived(TrkResult)), this, SLOT(slotHandleResult(TrkResult))); +} + +TrkWriteQueueDevice::~TrkWriteQueueDevice() +{ + delete qd; +} + +unsigned char TrkWriteQueueDevice::nextTrkWriteToken() +{ + ++qd->trkWriteToken; + if (qd->trkWriteToken == 0) + ++qd->trkWriteToken; + return qd->trkWriteToken; +} + +void TrkWriteQueueDevice::sendTrkMessage(unsigned char code, Callback callback, + const QByteArray &data, const QVariant &cookie, + bool invokeOnNAK) +{ + TrkMessage msg(code, nextTrkWriteToken(), callback); + msg.data = data; + msg.cookie = cookie; + msg.invokeOnNAK = invokeOnNAK; + queueTrkMessage(msg); +} + +void TrkWriteQueueDevice::sendTrkInitialPing() +{ + const TrkMessage msg(0, 0); // Ping, reset sequence count + queueTrkMessage(msg); +} + +bool TrkWriteQueueDevice::sendTrkAck(unsigned char token) +{ + TrkMessage msg(0x80, token); + msg.token = token; + msg.data.append('\0'); + // The acknowledgement must not be queued! + return trkWriteRawMessage(msg); + // 01 90 00 07 7e 80 01 00 7d 5e 7e +} + +void TrkWriteQueueDevice::queueTrkMessage(const TrkMessage &msg) +{ + qd->trkWriteQueue.append(msg); +} + +void TrkWriteQueueDevice::tryTrkWrite() +{ + // Invoked from timer, try to flush out message queue + if (qd->trkWriteBusy) + return; + if (qd->trkWriteQueue.isEmpty()) + return; + + const TrkMessage msg = qd->trkWriteQueue.dequeue(); + trkWrite(msg); +} + +bool TrkWriteQueueDevice::trkWriteRawMessage(const TrkMessage &msg) +{ + const QByteArray ba = frameMessage(msg.code, msg.token, msg.data, serialFrame()); + if (verbose()) + qDebug() << ("WRITE: " + stringFromArray(ba)); + QString errorMessage; + const bool rc = write(ba, &errorMessage); + if (!rc) + emitError(errorMessage); + return rc; +} + +bool TrkWriteQueueDevice::trkWrite(const TrkMessage &msg) +{ + qd->writtenTrkMessages.insert(msg.token, msg); + qd->trkWriteBusy = true; + return trkWriteRawMessage(msg); +} + +void TrkWriteQueueDevice::timerEvent(QTimerEvent *ev) +{ + tryTrkWrite(); + TrkDevice::timerEvent(ev); +} + +void TrkWriteQueueDevice::slotHandleResult(const TrkResult &result) +{ + qd->trkWriteBusy = false; + if (result.code != TrkNotifyAck && result.code != TrkNotifyNak) + return; + // Find which request the message belongs to and invoke callback + // if ACK or on NAK if desired. + const TrkWriteQueueDevicePrivate::TokenMessageMap::iterator it = qd->writtenTrkMessages.find(result.token); + if (it == qd->writtenTrkMessages.end()) + return; + const bool invokeCB = it.value().callback + && (result.code == TrkNotifyAck || it.value().invokeOnNAK); + + if (invokeCB) { + TrkResult result1 = result; + result1.cookie = it.value().cookie; + it.value().callback(result1); + } + qd->writtenTrkMessages.erase(it); +} + +} // namespace tr diff --git a/tests/manual/trk/trkdevice.h b/tests/manual/trk/trkdevice.h index 7392c8a62c3..53047bfb899 100644 --- a/tests/manual/trk/trkdevice.h +++ b/tests/manual/trk/trkdevice.h @@ -30,6 +30,8 @@ #ifndef TRKDEVICE_H #define TRKDEVICE_H +#include "trkfunctor.h" + #include <QtCore/QObject> #include <QtCore/QVariant> #include <QtCore/QByteArray> @@ -37,7 +39,9 @@ namespace trk { struct TrkResult; +struct TrkMessage; struct TrkDevicePrivate; +struct TrkWriteQueueDevicePrivate; /* TrkDevice: Implements a Windows COM or Linux device for * Trk communications. Provides synchronous write and asynchronous @@ -71,14 +75,62 @@ public: signals: void messageReceived(const TrkResult&); + void error(const QString &s); + +protected: + void emitError(const QString &); + virtual void timerEvent(QTimerEvent *ev); private: void tryTrkRead(); - virtual void timerEvent(QTimerEvent *ev); TrkDevicePrivate *d; }; +/* TrkWriteQueueDevice: Extends TrkDevice by write message queue allowing + * for queueing messages with a notification callback. If the message receives + * an ACK, the callback is invoked. */ +class TrkWriteQueueDevice : public TrkDevice +{ + Q_OBJECT +public: + explicit TrkWriteQueueDevice(QObject *parent = 0); + virtual ~TrkWriteQueueDevice(); + + // Construct as 'TrkWriteQueueDevice::Callback(instance, &Klass::method);' + typedef TrkFunctor1<const TrkResult &> Callback; + + // Enqueue a message with a notification callback. + void sendTrkMessage(unsigned char code, + Callback callBack = Callback(), + const QByteArray &data = QByteArray(), + const QVariant &cookie = QVariant(), + // Invoke callback on receiving NAK, too. + bool invokeOnNAK = false); + + // Enqeue an initial ping + void sendTrkInitialPing(); + + // Send an Ack synchronously, bypassing the queue + bool sendTrkAck(unsigned char token); + +private slots: + void slotHandleResult(const TrkResult &); + +protected: + virtual void timerEvent(QTimerEvent *ev); + +private: + unsigned char nextTrkWriteToken(); + void queueTrkMessage(const TrkMessage &msg); + void tryTrkWrite(); + bool trkWriteRawMessage(const TrkMessage &msg); + bool trkWrite(const TrkMessage &msg); + + TrkWriteQueueDevicePrivate *qd; +}; + + } // namespace trk #endif // TRKDEVICE_H diff --git a/tests/manual/trk/trkfunctor.h b/tests/manual/trk/trkfunctor.h new file mode 100644 index 00000000000..69a67e97a61 --- /dev/null +++ b/tests/manual/trk/trkfunctor.h @@ -0,0 +1,144 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef _TRK_FUNCTOR_H_ +#define _TRK_FUNCTOR_H_ + +#include <QtGlobal> + +namespace trk { +namespace Internal { +/* Helper class for the 1-argument functor: + * Cloneable base class for the implementation which is + * invokeable with the argument. */ +template <class Argument> +class TrkFunctor1ImplBase { + Q_DISABLE_COPY(TrkFunctor1ImplBase) +public: + TrkFunctor1ImplBase() {} + virtual TrkFunctor1ImplBase *clone() const = 0; + virtual void invoke(Argument a) = 0; + virtual ~TrkFunctor1ImplBase() {} +}; + +/* Helper class for the 1-argument functor: Implementation for + * a class instance with a member function pointer. */ +template <class Klass, class Argument> +class TrkFunctor1MemberPtrImpl : public TrkFunctor1ImplBase<Argument> { +public: + typedef void (Klass::*MemberFuncPtr)(Argument); + + explicit TrkFunctor1MemberPtrImpl(Klass *instance, + MemberFuncPtr memberFunc) : + m_instance(instance), + m_memberFunc(memberFunc) {} + + virtual TrkFunctor1ImplBase<Argument> *clone() const + { + return new TrkFunctor1MemberPtrImpl<Klass, Argument>(m_instance, m_memberFunc); + } + + virtual void invoke(Argument a) + { (m_instance->*m_memberFunc)(a); } +private: + Klass *m_instance; + MemberFuncPtr m_memberFunc; +}; + +} // namespace Internal + +/* Default-constructible, copyable 1-argument functor providing an + * operator()(Argument) that invokes a member function of a class: + * \code +class Foo { +public: + void print(const std::string &); +}; +... +Foo foo; +TrkFunctor1<const std::string &> f1(&foo, &Foo::print); +f1("test"); +\endcode */ + +template <class Argument> +class TrkFunctor1 { +public: + TrkFunctor1() : m_impl(0) {} + + template <class Klass> + TrkFunctor1(Klass *instance, + void (Klass::*memberFunc)(Argument)) : + m_impl(new Internal::TrkFunctor1MemberPtrImpl<Klass,Argument>(instance, memberFunc)) {} + + ~TrkFunctor1() + { + clean(); + } + + TrkFunctor1(const TrkFunctor1 &rhs) : + m_impl(0) + { + if (rhs.m_impl) + m_impl = rhs.m_impl->clone(); + } + + TrkFunctor1 &operator=(const TrkFunctor1 &rhs) + { + if (this != &rhs) { + clean(); + if (rhs.m_impl) + m_impl = rhs.m_impl->clone(); + } + return *this; + } + + inline bool isNull() const { return m_impl == 0; } + operator bool() const { return !isNull(); } + + void operator()(Argument a) + { + if (m_impl) + m_impl->invoke(a); + } + +private: + void clean() + { + if (m_impl) { + delete m_impl; + m_impl = 0; + } + } + + Internal::TrkFunctor1ImplBase<Argument> *m_impl; +}; + +} // namespace trk + +#endif // _TRK_FUNCTOR_H_ diff --git a/tests/manual/trk/trklauncher.pri b/tests/manual/trk/trklauncher.pri index 8824c4a5c40..3593888b861 100644 --- a/tests/manual/trk/trklauncher.pri +++ b/tests/manual/trk/trklauncher.pri @@ -4,5 +4,6 @@ SOURCES += $$PWD/launcher.cpp \ $$PWD/trkutils.cpp \ $$PWD/trkdevice.cpp HEADERS += $$PWD/trkutils.h \ + $$PWD/trkfunctor.h \ $$PWD/trkdevice.h \ $$PWD/launcher.h -- GitLab