VcsBaseDiffEditorController: Get rid of VcsCommandResultProxy

The workaround with VcsCommandResultProxy, introduced in
0b1eaacabb isn't needed anymore
since finished() and stdOutText() signals are now emitted
synchronously from the caller's thread.

Give a context object to watcher's finished handler.

Change-Id: I6608b7c2806fc0c18649ff40f91684e9eaa7b15d
Reviewed-by: Orgad Shaneh <orgads@gmail.com>
This commit is contained in:
Jarek Kobus
2022-09-16 11:45:28 +02:00
parent 60098e5fea
commit 73e48ef275

View File

@@ -33,35 +33,6 @@ static void readPatch(QFutureInterface<QList<FileData>> &futureInterface,
///////////////////// /////////////////////
// We need a way to disconnect from signals posted from different thread
// so that signals that are already posted from the other thread and not delivered
// yet will be ignored. Unfortunately, simple QObject::disconnect() doesn't
// work like that, since signals that are already posted and are awaiting
// to be delivered WILL BE delivered later, even after a call to QObject::disconnect().
// The delivery will happen when the control returns to the main event loop.
// This proxy class solves the above problem. Instead of a call to
// QObject::disconnect(), which would still deliver posted signals,
// we delete the proxy object immediately. In this way signals which are
// already posted and are awaiting to be delivered won't be delivered to the
// destroyed object.
// So the only reason for this proxy object is to be able to disconnect
// effectively from the signals posted from different threads.
class VcsCommandResultProxy : public QObject {
Q_OBJECT
public:
VcsCommandResultProxy(VcsCommand *command, VcsBaseDiffEditorControllerPrivate *target);
private:
void storeOutput(const QString &output);
void commandFinished(bool success);
VcsBaseDiffEditorControllerPrivate *m_target;
};
/////////////////////
class VcsBaseDiffEditorControllerPrivate class VcsBaseDiffEditorControllerPrivate
{ {
public: public:
@@ -71,7 +42,6 @@ public:
void processingFinished(); void processingFinished();
void processDiff(const QString &patch); void processDiff(const QString &patch);
void cancelReload(); void cancelReload();
void storeOutput(const QString &output);
void commandFinished(bool success); void commandFinished(bool success);
VcsBaseDiffEditorController *q; VcsBaseDiffEditorController *q;
@@ -83,37 +53,12 @@ public:
QString m_output; QString m_output;
QString m_displayName; QString m_displayName;
QPointer<VcsCommand> m_command; QPointer<VcsCommand> m_command;
QPointer<VcsCommandResultProxy> m_commandResultProxy;
QFutureWatcher<QList<FileData>> *m_processWatcher = nullptr; QFutureWatcher<QList<FileData>> *m_processWatcher = nullptr;
}; };
/////////////////////
VcsCommandResultProxy::VcsCommandResultProxy(VcsCommand *command,
VcsBaseDiffEditorControllerPrivate *target)
: QObject(target->q)
, m_target(target)
{
connect(command, &VcsCommand::stdOutText,
this, &VcsCommandResultProxy::storeOutput);
connect(command, &VcsCommand::finished,
this, &VcsCommandResultProxy::commandFinished);
connect(command, &VcsCommand::destroyed,
this, &QObject::deleteLater);
}
void VcsCommandResultProxy::storeOutput(const QString &output)
{
m_target->storeOutput(output);
}
void VcsCommandResultProxy::commandFinished(bool success)
{
m_target->commandFinished(success);
}
VcsBaseDiffEditorControllerPrivate::~VcsBaseDiffEditorControllerPrivate() VcsBaseDiffEditorControllerPrivate::~VcsBaseDiffEditorControllerPrivate()
{ {
delete m_command;
cancelReload(); cancelReload();
} }
@@ -142,8 +87,8 @@ void VcsBaseDiffEditorControllerPrivate::processDiff(const QString &patch)
m_processWatcher = new QFutureWatcher<QList<FileData>>(); m_processWatcher = new QFutureWatcher<QList<FileData>>();
QObject::connect(m_processWatcher, &QFutureWatcher<QList<FileData>>::finished, QObject::connect(m_processWatcher, &QFutureWatcherBase::finished,
[this] () { processingFinished(); } ); q, [this] { processingFinished(); });
m_processWatcher->setFuture(Utils::runAsync(&readPatch, patch)); m_processWatcher->setFuture(Utils::runAsync(&readPatch, patch));
@@ -153,14 +98,7 @@ void VcsBaseDiffEditorControllerPrivate::processDiff(const QString &patch)
void VcsBaseDiffEditorControllerPrivate::cancelReload() void VcsBaseDiffEditorControllerPrivate::cancelReload()
{ {
if (m_command) { m_command.clear();
m_command->cancel();
m_command.clear();
}
// Disconnect effectively, don't deliver already posted signals
if (m_commandResultProxy)
delete m_commandResultProxy.data();
if (m_processWatcher) { if (m_processWatcher) {
// Cancel the running process without the further processingFinished() // Cancel the running process without the further processingFinished()
@@ -173,24 +111,11 @@ void VcsBaseDiffEditorControllerPrivate::cancelReload()
m_output = QString(); m_output = QString();
} }
void VcsBaseDiffEditorControllerPrivate::storeOutput(const QString &output)
{
m_output = output;
}
void VcsBaseDiffEditorControllerPrivate::commandFinished(bool success) void VcsBaseDiffEditorControllerPrivate::commandFinished(bool success)
{ {
if (m_command) // Don't delete here, as it is called from command finished signal.
m_command.clear(); // Clear it only, as we may call runCommand() again from inside processCommandOutput overload.
m_command.clear();
// Prevent direct deletion of m_commandResultProxy inside the possible
// subsequent synchronous calls to cancelReload() [called e.g. by
// processCommandOutput() overload], since
// commandFinished() is called directly by the m_commandResultProxy.
// m_commandResultProxy is removed via deleteLater right after
// a call to this commandFinished() is finished
if (m_commandResultProxy)
m_commandResultProxy.clear();
if (!success) { if (!success) {
cancelReload(); cancelReload();
@@ -198,7 +123,7 @@ void VcsBaseDiffEditorControllerPrivate::commandFinished(bool success)
return; return;
} }
q->processCommandOutput(QString(m_output)); // pass a copy of m_output q->processCommandOutput(m_output);
} }
///////////////////// /////////////////////
@@ -219,12 +144,16 @@ void VcsBaseDiffEditorController::runCommand(const QList<QStringList> &args, uns
// processingFinished() notifications, as right after that // processingFinished() notifications, as right after that
// we re-reload it from scratch. So no intermediate "Retrieving data failed." // we re-reload it from scratch. So no intermediate "Retrieving data failed."
// and "Waiting for data..." will be shown. // and "Waiting for data..." will be shown.
delete d->m_command;
d->cancelReload(); d->cancelReload();
d->m_command = VcsBaseClient::createVcsCommand(workingDirectory(), d->m_processEnvironment); d->m_command = VcsBaseClient::createVcsCommand(workingDirectory(), d->m_processEnvironment);
d->m_command->setDisplayName(d->m_displayName); d->m_command->setDisplayName(d->m_displayName);
d->m_command->setCodec(codec ? codec : EditorManager::defaultTextCodec()); d->m_command->setCodec(codec ? codec : EditorManager::defaultTextCodec());
d->m_commandResultProxy = new VcsCommandResultProxy(d->m_command.data(), d); connect(d->m_command.data(), &VcsCommand::stdOutText,
this, [this](const QString &output) { d->m_output = output; });
connect(d->m_command.data(), &VcsCommand::finished,
this, [this](bool success) { d->commandFinished(success); });
d->m_command->addFlags(flags); d->m_command->addFlags(flags);
for (const QStringList &arg : args) { for (const QStringList &arg : args) {
@@ -283,5 +212,3 @@ void VcsBaseDiffEditorController::setProcessEnvironment(const Environment &value
} }
} // namespace VcsBase } // namespace VcsBase
#include "vcsbasediffeditorcontroller.moc"