Add some more comments

Add some developer comments explaining which method
is designed to be called from a certain thread.
Add also some comments about in which thread
certain QObjects live in.

Change-Id: I38b10216cc29f8a86fd784e588e913407f0fb776
Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
Jarek Kobus
2021-08-18 10:45:57 +02:00
parent fd6ab7ddab
commit a7e8ddd725
4 changed files with 44 additions and 25 deletions

View File

@@ -210,11 +210,13 @@ LauncherInterface::~LauncherInterface()
void LauncherInterface::startLauncher() void LauncherInterface::startLauncher()
{ {
// Call in launcher's thread.
QMetaObject::invokeMethod(instance().m_private, &LauncherInterfacePrivate::doStart); QMetaObject::invokeMethod(instance().m_private, &LauncherInterfacePrivate::doStart);
} }
void LauncherInterface::stopLauncher() void LauncherInterface::stopLauncher()
{ {
// Call in launcher's thread.
QMetaObject::invokeMethod(instance().m_private, &LauncherInterfacePrivate::doStop); QMetaObject::invokeMethod(instance().m_private, &LauncherInterfacePrivate::doStop);
} }

View File

@@ -39,9 +39,10 @@ class CallerHandle : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
// Called from caller's thread exclusively, lives in caller's thread.
CallerHandle() : QObject() {} CallerHandle() : QObject() {}
// Always called in caller's thread. Returns the list of flushed signals. // Called from caller's thread exclusively. Returns the list of flushed signals.
QList<LauncherHandle::SignalType> flush() QList<LauncherHandle::SignalType> flush()
{ {
QList<LauncherHandle::SignalType> oldSignals; QList<LauncherHandle::SignalType> oldSignals;
@@ -70,17 +71,7 @@ public:
} }
return oldSignals; return oldSignals;
} }
void appendSignal(LauncherHandle::SignalType signalType) // Called from caller's thread exclusively.
{
if (signalType == LauncherHandle::SignalType::NoSignal)
return;
QMutexLocker locker(&m_mutex);
if (m_signals.contains(signalType))
return;
m_signals.append(signalType);
}
bool shouldFlushFor(LauncherHandle::SignalType signalType) bool shouldFlushFor(LauncherHandle::SignalType signalType)
{ {
// TODO: Should we always flush when the list isn't empty? // TODO: Should we always flush when the list isn't empty?
@@ -93,7 +84,20 @@ public:
return true; return true;
return false; return false;
} }
// Called from launcher's thread exclusively.
void appendSignal(LauncherHandle::SignalType signalType)
{
if (signalType == LauncherHandle::SignalType::NoSignal)
return;
QMutexLocker locker(&m_mutex);
if (m_signals.contains(signalType))
return;
m_signals.append(signalType);
}
signals: signals:
// Emitted from caller's thread exclusively.
void errorOccurred(); void errorOccurred();
void started(); void started();
void readyRead(); void readyRead();
@@ -485,7 +489,7 @@ void LauncherSocket::sendData(const QByteArray &data)
return m_requests.size() == 1; // Returns true if requests handling should be triggered. return m_requests.size() == 1; // Returns true if requests handling should be triggered.
}; };
if (storeRequest(data)) if (storeRequest(data)) // Call handleRequests() in launcher's thread.
QMetaObject::invokeMethod(this, &LauncherSocket::handleRequests); QMetaObject::invokeMethod(this, &LauncherSocket::handleRequests);
} }

View File

@@ -55,14 +55,11 @@ class CallerHandle;
// It's assumed that this object will be alive at least // It's assumed that this object will be alive at least
// as long as the corresponding QtcProcess is alive. // as long as the corresponding QtcProcess is alive.
// We should have LauncherSocket::registerHandle() and LauncherSocket::unregisterHandle()
// methods.
class LauncherHandle : public QObject class LauncherHandle : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
// called from main thread // All the public methods in this class are called exclusively from the caller's thread.
bool waitForStarted(int msecs) bool waitForStarted(int msecs)
{ return waitForSignal(msecs, SignalType::Started); } { return waitForSignal(msecs, SignalType::Started); }
bool waitForReadyRead(int msces) bool waitForReadyRead(int msces)
@@ -122,25 +119,30 @@ private:
ReadyRead, ReadyRead,
Finished Finished
}; };
// called from other thread
// Called from caller's thread exclusively.
bool waitForSignal(int msecs, SignalType newSignal); bool waitForSignal(int msecs, SignalType newSignal);
bool doWaitForSignal(int msecs, SignalType newSignal); bool doWaitForSignal(int msecs, SignalType newSignal);
bool canWaitFor(SignalType newSignal) const; bool canWaitFor(SignalType newSignal) const;
// Called from caller's or launcher's thread.
void doStart(); void doStart();
// Called from caller's thread exclusively.
void slotErrorOccurred(); void slotErrorOccurred();
void slotStarted(); void slotStarted();
void slotReadyRead(); void slotReadyRead();
void slotFinished(); void slotFinished();
// called from this thread // Called from caller's thread, moved to launcher's thread.
LauncherHandle(quintptr token, ProcessMode mode) : m_token(token), m_processMode(mode) {} LauncherHandle(quintptr token, ProcessMode mode) : m_token(token), m_processMode(mode) {}
// Called from caller's thread exclusively.
void createCallerHandle(); void createCallerHandle();
void destroyCallerHandle(); void destroyCallerHandle();
// Called from launcher's thread exclusively.
void flushCaller(); void flushCaller();
void handlePacket(LauncherPacketType type, const QByteArray &payload); void handlePacket(LauncherPacketType type, const QByteArray &payload);
void handleErrorPacket(const QByteArray &packetData); void handleErrorPacket(const QByteArray &packetData);
void handleStartedPacket(const QByteArray &packetData); void handleStartedPacket(const QByteArray &packetData);
@@ -148,18 +150,22 @@ private:
void handleReadyReadStandardError(const QByteArray &packetData); void handleReadyReadStandardError(const QByteArray &packetData);
void handleFinishedPacket(const QByteArray &packetData); void handleFinishedPacket(const QByteArray &packetData);
// Called from launcher's thread exclusively.
void handleSocketReady(); void handleSocketReady();
void handleSocketError(const QString &message); void handleSocketError(const QString &message);
// Called from launcher's thread exclusively.
void wakeUpIfWaitingFor(SignalType newSignal); void wakeUpIfWaitingFor(SignalType newSignal);
QByteArray readAndClear(QByteArray &data) // Called from caller's thread exclusively.
QByteArray readAndClear(QByteArray &data) const
{ {
const QByteArray tmp = data; const QByteArray tmp = data;
data.clear(); data.clear();
return tmp; return tmp;
} }
// Called from caller's or launcher's thread.
void sendPacket(const Internal::LauncherPacket &packet); void sendPacket(const Internal::LauncherPacket &packet);
mutable QMutex m_mutex; mutable QMutex m_mutex;
@@ -169,7 +175,8 @@ private:
SignalType m_waitingFor = SignalType::NoSignal; SignalType m_waitingFor = SignalType::NoSignal;
QProcess::ProcessState m_processState = QProcess::NotRunning; QProcess::ProcessState m_processState = QProcess::NotRunning;
bool m_awaitingShouldContinue = false; // cancel() sets it to false, modified only in caller's thread // cancel() sets it to false, modified only in caller's thread.
bool m_awaitingShouldContinue = false;
int m_processId = 0; int m_processId = 0;
int m_exitCode = 0; int m_exitCode = 0;
QProcess::ExitStatus m_exitStatus = QProcess::ExitStatus::NormalExit; QProcess::ExitStatus m_exitStatus = QProcess::ExitStatus::NormalExit;
@@ -187,6 +194,7 @@ private:
QProcess::ProcessChannelMode m_channelMode = QProcess::SeparateChannels; QProcess::ProcessChannelMode m_channelMode = QProcess::SeparateChannels;
QString m_standardInputFile; QString m_standardInputFile;
// Lives in caller's thread.
CallerHandle *m_callerHandle = nullptr; CallerHandle *m_callerHandle = nullptr;
bool m_belowNormalPriority = false; bool m_belowNormalPriority = false;
@@ -203,9 +211,11 @@ class LauncherSocket : public QObject
Q_OBJECT Q_OBJECT
friend class LauncherInterfacePrivate; friend class LauncherInterfacePrivate;
public: public:
// Called from caller's or launcher's thread.
bool isReady() const { return m_socket.load(); } bool isReady() const { return m_socket.load(); }
void sendData(const QByteArray &data); void sendData(const QByteArray &data);
// Called from caller's thread exclusively.
LauncherHandle *registerHandle(quintptr token, ProcessMode mode); LauncherHandle *registerHandle(quintptr token, ProcessMode mode);
void unregisterHandle(quintptr token); void unregisterHandle(quintptr token);
@@ -214,13 +224,17 @@ signals:
void errorOccurred(const QString &error); void errorOccurred(const QString &error);
private: private:
// Called from caller's thread, moved to launcher's thread.
LauncherSocket(QObject *parent = nullptr); LauncherSocket(QObject *parent = nullptr);
// Called from launcher's thread exclusively.
LauncherHandle *handleForToken(quintptr token) const; LauncherHandle *handleForToken(quintptr token) const;
// Called from launcher's thread exclusively.
void setSocket(QLocalSocket *socket); void setSocket(QLocalSocket *socket);
void shutdown(); void shutdown();
// Called from launcher's thread exclusively.
void handleSocketError(); void handleSocketError();
void handleSocketDataAvailable(); void handleSocketDataAvailable();
void handleSocketDisconnected(); void handleSocketDisconnected();

View File

@@ -310,8 +310,6 @@ private:
typedef void (ProcessLauncherImpl::*PreSignal)(void); typedef void (ProcessLauncherImpl::*PreSignal)(void);
void cancel(); void cancel();
void sendPacket(const Internal::LauncherPacket &packet)
{ LauncherInterface::socket()->sendData(packet.serialize()); }
void handleSocketError(const QString &message); void handleSocketError(const QString &message);
void handleSocketReady(); void handleSocketReady();
@@ -319,7 +317,8 @@ private:
quintptr token() const { return m_token; } quintptr token() const { return m_token; }
const uint m_token = 0; const uint m_token = 0;
LauncherHandle *m_handle = nullptr; // This object lives in a different thread! // Lives in launcher's thread.
LauncherHandle *m_handle = nullptr;
}; };
void ProcessLauncherImpl::cancel() void ProcessLauncherImpl::cancel()