forked from qt-creator/qt-creator
Introduce Utils::Singleton
Introduce Utils::Singleton class and Utils::SingletonWithOptionalDependencies class template that helps implementing singletons that depend on other singletons. It's guaranteed that whenever singleton B depends on singleton A, than A is always created before B is being created, and that the order of destruction is always opposite to the order of creation. Dependencies of singleton are listed as template arguments for SingletonWithOptionalDependencies class template. The first argument of SingletonWithOptionalDependencies class template is always a singleton class itself. Prepare a common interface for all singleton subclasses: SingletonSubClass *SingletonWithOptionalDependencies::instance(); Make instantiating singletons and its dependencies thread-safe. Create singletons on demand (only if some code needs them). It's not needed anymore to explicitly instantiate all required singletons in tests. Make it possible (and thread-safe) to instantiate ProcessReaper and LauncherInterface singletons in non-main threads. Make the following dependencies between existing singletons: SshConnectionManager depends on: -> LauncherInterface depends on: -> ProcessReaper Change-Id: Iefaacab561c2b3dcf07e7fafbb87339ea6a15278 Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
This commit is contained in:
@@ -12,7 +12,7 @@ install(
|
|||||||
|
|
||||||
add_qtc_executable(qtcreator
|
add_qtc_executable(qtcreator
|
||||||
DEFINES IDE_LIBRARY_BASENAME=\"${IDE_LIBRARY_BASE_PATH}\"
|
DEFINES IDE_LIBRARY_BASENAME=\"${IDE_LIBRARY_BASE_PATH}\"
|
||||||
DEPENDS Aggregation ExtensionSystem Qt5::Core Qt5::Widgets Utils QtcSsh shared_qtsingleapplication app_version
|
DEPENDS Aggregation ExtensionSystem Qt5::Core Qt5::Widgets Utils shared_qtsingleapplication app_version
|
||||||
SOURCES
|
SOURCES
|
||||||
main.cpp
|
main.cpp
|
||||||
../tools/qtcreatorcrashhandler/crashhandlersetup.cpp ../tools/qtcreatorcrashhandler/crashhandlersetup.h
|
../tools/qtcreatorcrashhandler/crashhandlersetup.cpp ../tools/qtcreatorcrashhandler/crashhandlersetup.h
|
||||||
|
@@ -17,7 +17,7 @@ include(../rpath.pri)
|
|||||||
|
|
||||||
include(../libs/qt-breakpad/qtbreakpad.pri)
|
include(../libs/qt-breakpad/qtbreakpad.pri)
|
||||||
|
|
||||||
LIBS *= -l$$qtLibraryName(ExtensionSystem) -l$$qtLibraryName(Aggregation) -l$$qtLibraryName(Utils) -l$$qtLibraryName(QtcSsh)
|
LIBS *= -l$$qtLibraryName(ExtensionSystem) -l$$qtLibraryName(Aggregation) -l$$qtLibraryName(Utils)
|
||||||
|
|
||||||
win32 {
|
win32 {
|
||||||
# We need the version in two separate formats for the .rc file
|
# We need the version in two separate formats for the .rc file
|
||||||
|
@@ -46,7 +46,6 @@ QtcProduct {
|
|||||||
Depends { name: "app_version_header" }
|
Depends { name: "app_version_header" }
|
||||||
Depends { name: "Qt"; submodules: ["widgets", "network"] }
|
Depends { name: "Qt"; submodules: ["widgets", "network"] }
|
||||||
Depends { name: "Utils" }
|
Depends { name: "Utils" }
|
||||||
Depends { name: "QtcSsh" }
|
|
||||||
Depends { name: "ExtensionSystem" }
|
Depends { name: "ExtensionSystem" }
|
||||||
|
|
||||||
files: [
|
files: [
|
||||||
|
@@ -32,16 +32,13 @@
|
|||||||
#include <extensionsystem/pluginspec.h>
|
#include <extensionsystem/pluginspec.h>
|
||||||
#include <qtsingleapplication.h>
|
#include <qtsingleapplication.h>
|
||||||
|
|
||||||
#include <ssh/sshconnectionmanager.h>
|
|
||||||
|
|
||||||
#include <utils/algorithm.h>
|
#include <utils/algorithm.h>
|
||||||
#include <utils/environment.h>
|
#include <utils/environment.h>
|
||||||
#include <utils/fileutils.h>
|
#include <utils/fileutils.h>
|
||||||
#include <utils/hostosinfo.h>
|
#include <utils/hostosinfo.h>
|
||||||
#include <utils/launcherinterface.h>
|
|
||||||
#include <utils/optional.h>
|
#include <utils/optional.h>
|
||||||
#include <utils/processreaper.h>
|
|
||||||
#include <utils/qtcsettings.h>
|
#include <utils/qtcsettings.h>
|
||||||
|
#include <utils/singleton.h>
|
||||||
#include <utils/temporarydirectory.h>
|
#include <utils/temporarydirectory.h>
|
||||||
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
@@ -537,10 +534,7 @@ int main(int argc, char **argv)
|
|||||||
QCoreApplication::setOrganizationName(QLatin1String(Core::Constants::IDE_SETTINGSVARIANT_STR));
|
QCoreApplication::setOrganizationName(QLatin1String(Core::Constants::IDE_SETTINGSVARIANT_STR));
|
||||||
QGuiApplication::setApplicationDisplayName(Core::Constants::IDE_DISPLAY_NAME);
|
QGuiApplication::setApplicationDisplayName(Core::Constants::IDE_DISPLAY_NAME);
|
||||||
|
|
||||||
Utils::ProcessReaper processReaper;
|
auto cleanup = qScopeGuard([] { Utils::Singleton::deleteAll(); });
|
||||||
Utils::LauncherInterface::startLauncher();
|
|
||||||
auto cleanup = qScopeGuard([] { Utils::LauncherInterface::stopLauncher(); });
|
|
||||||
QSsh::SshConnectionManager sshConnectionManager;
|
|
||||||
|
|
||||||
const QStringList pluginArguments = app.arguments();
|
const QStringList pluginArguments = app.arguments();
|
||||||
|
|
||||||
|
@@ -53,16 +53,11 @@ bool operator!=(const UnacquiredConnection &c1, const UnacquiredConnection &c2)
|
|||||||
return !(c1 == c2);
|
return !(c1 == c2);
|
||||||
}
|
}
|
||||||
|
|
||||||
static class SshConnectionManagerPrivate *s_instance = nullptr;
|
|
||||||
|
|
||||||
class SshConnectionManagerPrivate : public QObject
|
class SshConnectionManagerPrivate : public QObject
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SshConnectionManagerPrivate()
|
SshConnectionManagerPrivate()
|
||||||
{
|
{
|
||||||
QTC_ASSERT(s_instance == nullptr, return);
|
|
||||||
s_instance = this;
|
|
||||||
|
|
||||||
connect(&m_removalTimer, &QTimer::timeout,
|
connect(&m_removalTimer, &QTimer::timeout,
|
||||||
this, &SshConnectionManagerPrivate::removeInactiveConnections);
|
this, &SshConnectionManagerPrivate::removeInactiveConnections);
|
||||||
m_removalTimer.start(SshSettings::connectionSharingTimeout() * 1000 * 60 / 2);
|
m_removalTimer.start(SshSettings::connectionSharingTimeout() * 1000 * 60 / 2);
|
||||||
@@ -70,8 +65,6 @@ public:
|
|||||||
|
|
||||||
~SshConnectionManagerPrivate() override
|
~SshConnectionManagerPrivate() override
|
||||||
{
|
{
|
||||||
QTC_ASSERT(s_instance == this, return);
|
|
||||||
|
|
||||||
for (const UnacquiredConnection &connection : qAsConst(m_unacquiredConnections)) {
|
for (const UnacquiredConnection &connection : qAsConst(m_unacquiredConnections)) {
|
||||||
disconnect(connection.connection, nullptr, this, nullptr);
|
disconnect(connection.connection, nullptr, this, nullptr);
|
||||||
delete connection.connection;
|
delete connection.connection;
|
||||||
@@ -79,8 +72,6 @@ public:
|
|||||||
|
|
||||||
QTC_CHECK(m_acquiredConnections.isEmpty());
|
QTC_CHECK(m_acquiredConnections.isEmpty());
|
||||||
QTC_CHECK(m_deprecatedConnections.isEmpty());
|
QTC_CHECK(m_deprecatedConnections.isEmpty());
|
||||||
|
|
||||||
s_instance = nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SshConnection *acquireConnection(const SshConnectionParameters &sshParams)
|
SshConnection *acquireConnection(const SshConnectionParameters &sshParams)
|
||||||
@@ -213,6 +204,7 @@ private:
|
|||||||
SshConnectionManager::SshConnectionManager()
|
SshConnectionManager::SshConnectionManager()
|
||||||
: d(new Internal::SshConnectionManagerPrivate())
|
: d(new Internal::SshConnectionManagerPrivate())
|
||||||
{
|
{
|
||||||
|
QTC_CHECK(QThread::currentThread() == qApp->thread());
|
||||||
}
|
}
|
||||||
|
|
||||||
SshConnectionManager::~SshConnectionManager()
|
SshConnectionManager::~SshConnectionManager()
|
||||||
@@ -222,20 +214,17 @@ SshConnectionManager::~SshConnectionManager()
|
|||||||
|
|
||||||
SshConnection *SshConnectionManager::acquireConnection(const SshConnectionParameters &sshParams)
|
SshConnection *SshConnectionManager::acquireConnection(const SshConnectionParameters &sshParams)
|
||||||
{
|
{
|
||||||
QTC_ASSERT(Internal::s_instance, return nullptr);
|
return instance()->d->acquireConnection(sshParams);
|
||||||
return Internal::s_instance->acquireConnection(sshParams);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SshConnectionManager::releaseConnection(SshConnection *connection)
|
void SshConnectionManager::releaseConnection(SshConnection *connection)
|
||||||
{
|
{
|
||||||
QTC_ASSERT(Internal::s_instance, return);
|
instance()->d->releaseConnection(connection);
|
||||||
Internal::s_instance->releaseConnection(connection);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SshConnectionManager::forceNewConnection(const SshConnectionParameters &sshParams)
|
void SshConnectionManager::forceNewConnection(const SshConnectionParameters &sshParams)
|
||||||
{
|
{
|
||||||
QTC_ASSERT(Internal::s_instance, return);
|
instance()->d->forceNewConnection(sshParams);
|
||||||
Internal::s_instance->forceNewConnection(sshParams);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace QSsh
|
} // namespace QSsh
|
||||||
|
@@ -27,6 +27,9 @@
|
|||||||
|
|
||||||
#include "ssh_global.h"
|
#include "ssh_global.h"
|
||||||
|
|
||||||
|
#include <utils/launcherinterface.h>
|
||||||
|
#include <utils/singleton.h>
|
||||||
|
|
||||||
namespace QSsh {
|
namespace QSsh {
|
||||||
|
|
||||||
class SshConnection;
|
class SshConnection;
|
||||||
@@ -35,18 +38,21 @@ class SshConnectionParameters;
|
|||||||
namespace Internal { class SshConnectionManagerPrivate; }
|
namespace Internal { class SshConnectionManagerPrivate; }
|
||||||
|
|
||||||
class QSSH_EXPORT SshConnectionManager final
|
class QSSH_EXPORT SshConnectionManager final
|
||||||
|
: public Utils::SingletonWithOptionalDependencies<SshConnectionManager,
|
||||||
|
Utils::LauncherInterface>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SshConnectionManager();
|
|
||||||
~SshConnectionManager();
|
|
||||||
|
|
||||||
static SshConnection *acquireConnection(const SshConnectionParameters &sshParams);
|
static SshConnection *acquireConnection(const SshConnectionParameters &sshParams);
|
||||||
static void releaseConnection(SshConnection *connection);
|
static void releaseConnection(SshConnection *connection);
|
||||||
// Make sure the next acquireConnection with the given parameters will return a new connection.
|
// Make sure the next acquireConnection with the given parameters will return a new connection.
|
||||||
static void forceNewConnection(const SshConnectionParameters &sshParams);
|
static void forceNewConnection(const SshConnectionParameters &sshParams);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
SshConnectionManager();
|
||||||
|
~SshConnectionManager();
|
||||||
|
|
||||||
Internal::SshConnectionManagerPrivate *d;
|
Internal::SshConnectionManagerPrivate *d;
|
||||||
|
friend class Utils::SingletonWithOptionalDependencies<SshConnectionManager, Utils::LauncherInterface>;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace QSsh
|
} // namespace QSsh
|
||||||
|
@@ -144,6 +144,7 @@ add_qtc_library(Utils
|
|||||||
settingsutils.h
|
settingsutils.h
|
||||||
shellcommand.cpp shellcommand.h
|
shellcommand.cpp shellcommand.h
|
||||||
shellcommandpage.cpp shellcommandpage.h
|
shellcommandpage.cpp shellcommandpage.h
|
||||||
|
singleton.cpp singleton.h
|
||||||
sizedarray.h
|
sizedarray.h
|
||||||
smallstring.h
|
smallstring.h
|
||||||
smallstringfwd.h
|
smallstringfwd.h
|
||||||
|
@@ -28,7 +28,6 @@
|
|||||||
#include "filepath.h"
|
#include "filepath.h"
|
||||||
#include "launcherpackets.h"
|
#include "launcherpackets.h"
|
||||||
#include "launchersocket.h"
|
#include "launchersocket.h"
|
||||||
#include "processreaper.h"
|
|
||||||
#include "qtcassert.h"
|
#include "qtcassert.h"
|
||||||
|
|
||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
@@ -42,7 +41,6 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace Utils {
|
namespace Utils {
|
||||||
|
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
class LauncherProcess : public QProcess
|
class LauncherProcess : public QProcess
|
||||||
@@ -185,92 +183,73 @@ void LauncherInterfacePrivate::handleProcessStderr()
|
|||||||
using namespace Utils::Internal;
|
using namespace Utils::Internal;
|
||||||
|
|
||||||
static QMutex s_instanceMutex;
|
static QMutex s_instanceMutex;
|
||||||
static LauncherInterface *s_instance = nullptr;
|
static QString s_pathToLauncher;
|
||||||
|
static std::atomic_bool s_started = false;
|
||||||
|
|
||||||
LauncherInterface::LauncherInterface()
|
LauncherInterface::LauncherInterface()
|
||||||
: m_private(new LauncherInterfacePrivate())
|
: m_private(new LauncherInterfacePrivate())
|
||||||
{
|
{
|
||||||
m_private->moveToThread(&m_thread);
|
m_private->moveToThread(&m_thread);
|
||||||
connect(m_private, &LauncherInterfacePrivate::errorOccurred,
|
QObject::connect(&m_thread, &QThread::finished, m_private, &QObject::deleteLater);
|
||||||
this, &LauncherInterface::errorOccurred);
|
|
||||||
connect(&m_thread, &QThread::finished, m_private, &QObject::deleteLater);
|
|
||||||
m_thread.start();
|
m_thread.start();
|
||||||
}
|
m_thread.moveToThread(qApp->thread());
|
||||||
|
|
||||||
LauncherInterface::~LauncherInterface()
|
m_private->setPathToLauncher(s_pathToLauncher);
|
||||||
{
|
const FilePath launcherFilePath = FilePath::fromString(m_private->launcherFilePath())
|
||||||
m_thread.quit();
|
|
||||||
m_thread.wait();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Called from main thread
|
|
||||||
void LauncherInterface::startLauncher(const QString &pathToLauncher)
|
|
||||||
{
|
|
||||||
QMutexLocker locker(&s_instanceMutex);
|
|
||||||
QTC_ASSERT(s_instance == nullptr, return);
|
|
||||||
s_instance = new LauncherInterface();
|
|
||||||
LauncherInterfacePrivate *p = s_instance->m_private;
|
|
||||||
p->setPathToLauncher(pathToLauncher);
|
|
||||||
const FilePath launcherFilePath = FilePath::fromString(p->launcherFilePath())
|
|
||||||
.cleanPath().withExecutableSuffix();
|
.cleanPath().withExecutableSuffix();
|
||||||
auto launcherIsNotExecutable = [&launcherFilePath]() {
|
auto launcherIsNotExecutable = [&launcherFilePath]() {
|
||||||
qWarning() << "The Creator's process launcher"
|
qWarning() << "The Creator's process launcher"
|
||||||
<< launcherFilePath << "is not executable.";
|
<< launcherFilePath << "is not executable.";
|
||||||
};
|
};
|
||||||
QTC_ASSERT(launcherFilePath.isExecutableFile(), launcherIsNotExecutable(); return);
|
QTC_ASSERT(launcherFilePath.isExecutableFile(), launcherIsNotExecutable(); return);
|
||||||
|
s_started = true;
|
||||||
// Call in launcher's thread.
|
// Call in launcher's thread.
|
||||||
QMetaObject::invokeMethod(p, &LauncherInterfacePrivate::doStart);
|
QMetaObject::invokeMethod(m_private, &LauncherInterfacePrivate::doStart);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called from main thread
|
LauncherInterface::~LauncherInterface()
|
||||||
void LauncherInterface::stopLauncher()
|
|
||||||
{
|
{
|
||||||
QMutexLocker locker(&s_instanceMutex);
|
QMutexLocker locker(&s_instanceMutex);
|
||||||
QTC_ASSERT(s_instance != nullptr, return);
|
LauncherInterfacePrivate *p = instance()->m_private;
|
||||||
LauncherInterfacePrivate *p = s_instance->m_private;
|
|
||||||
// Call in launcher's thread.
|
// Call in launcher's thread.
|
||||||
QMetaObject::invokeMethod(p, &LauncherInterfacePrivate::doStop, Qt::BlockingQueuedConnection);
|
QMetaObject::invokeMethod(p, &LauncherInterfacePrivate::doStop, Qt::BlockingQueuedConnection);
|
||||||
delete s_instance;
|
m_thread.quit();
|
||||||
s_instance = nullptr;
|
m_thread.wait();
|
||||||
|
}
|
||||||
|
|
||||||
|
void LauncherInterface::setPathToLauncher(const QString &pathToLauncher)
|
||||||
|
{
|
||||||
|
s_pathToLauncher = pathToLauncher;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LauncherInterface::isStarted()
|
bool LauncherInterface::isStarted()
|
||||||
{
|
{
|
||||||
QMutexLocker locker(&s_instanceMutex);
|
return s_started;
|
||||||
return s_instance != nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LauncherInterface::isReady()
|
bool LauncherInterface::isReady()
|
||||||
{
|
{
|
||||||
QMutexLocker locker(&s_instanceMutex);
|
QMutexLocker locker(&s_instanceMutex);
|
||||||
QTC_ASSERT(s_instance != nullptr, return false);
|
return instance()->m_private->socket()->isReady();
|
||||||
|
|
||||||
return s_instance->m_private->socket()->isReady();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LauncherInterface::sendData(const QByteArray &data)
|
void LauncherInterface::sendData(const QByteArray &data)
|
||||||
{
|
{
|
||||||
QMutexLocker locker(&s_instanceMutex);
|
QMutexLocker locker(&s_instanceMutex);
|
||||||
QTC_ASSERT(s_instance != nullptr, return);
|
instance()->m_private->socket()->sendData(data);
|
||||||
|
|
||||||
s_instance->m_private->socket()->sendData(data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Utils::Internal::CallerHandle *LauncherInterface::registerHandle(QObject *parent, quintptr token,
|
Utils::Internal::CallerHandle *LauncherInterface::registerHandle(QObject *parent, quintptr token,
|
||||||
ProcessMode mode)
|
ProcessMode mode)
|
||||||
{
|
{
|
||||||
QMutexLocker locker(&s_instanceMutex);
|
QMutexLocker locker(&s_instanceMutex);
|
||||||
QTC_ASSERT(s_instance != nullptr, return nullptr);
|
return instance()->m_private->socket()->registerHandle(parent, token, mode);
|
||||||
|
|
||||||
return s_instance->m_private->socket()->registerHandle(parent, token, mode);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LauncherInterface::unregisterHandle(quintptr token)
|
void LauncherInterface::unregisterHandle(quintptr token)
|
||||||
{
|
{
|
||||||
QMutexLocker locker(&s_instanceMutex);
|
QMutexLocker locker(&s_instanceMutex);
|
||||||
QTC_ASSERT(s_instance != nullptr, return);
|
instance()->m_private->socket()->unregisterHandle(token);
|
||||||
|
|
||||||
s_instance->m_private->socket()->unregisterHandle(token);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Utils
|
} // namespace Utils
|
||||||
|
@@ -27,9 +27,10 @@
|
|||||||
|
|
||||||
#include "utils_global.h"
|
#include "utils_global.h"
|
||||||
|
|
||||||
|
#include "processreaper.h"
|
||||||
#include "processutils.h"
|
#include "processutils.h"
|
||||||
|
#include "singleton.h"
|
||||||
|
|
||||||
#include <QObject>
|
|
||||||
#include <QThread>
|
#include <QThread>
|
||||||
|
|
||||||
namespace Utils {
|
namespace Utils {
|
||||||
@@ -40,15 +41,11 @@ class LauncherInterfacePrivate;
|
|||||||
class ProcessLauncherImpl;
|
class ProcessLauncherImpl;
|
||||||
}
|
}
|
||||||
|
|
||||||
class QTCREATOR_UTILS_EXPORT LauncherInterface : public QObject
|
class QTCREATOR_UTILS_EXPORT LauncherInterface final
|
||||||
|
: public SingletonWithOptionalDependencies<LauncherInterface, ProcessReaper>
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
|
||||||
public:
|
public:
|
||||||
static void startLauncher(const QString &pathToLauncher = {});
|
static void setPathToLauncher(const QString &pathToLauncher);
|
||||||
static void stopLauncher();
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void errorOccurred(const QString &error);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class Utils::Internal::CallerHandle;
|
friend class Utils::Internal::CallerHandle;
|
||||||
@@ -63,10 +60,11 @@ private:
|
|||||||
static void unregisterHandle(quintptr token);
|
static void unregisterHandle(quintptr token);
|
||||||
|
|
||||||
LauncherInterface();
|
LauncherInterface();
|
||||||
~LauncherInterface() override;
|
~LauncherInterface();
|
||||||
|
|
||||||
QThread m_thread;
|
QThread m_thread;
|
||||||
Internal::LauncherInterfacePrivate *m_private;
|
Internal::LauncherInterfacePrivate *m_private;
|
||||||
|
friend class SingletonWithOptionalDependencies<LauncherInterface, ProcessReaper>;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Utils
|
} // namespace Utils
|
||||||
|
@@ -36,8 +36,6 @@ using namespace Utils;
|
|||||||
namespace Utils {
|
namespace Utils {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
static ProcessReaper *d = nullptr;
|
|
||||||
|
|
||||||
class Reaper final : public QObject
|
class Reaper final : public QObject
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -57,7 +55,7 @@ private:
|
|||||||
|
|
||||||
Reaper::Reaper(QProcess *p, int timeoutMs) : m_process(p)
|
Reaper::Reaper(QProcess *p, int timeoutMs) : m_process(p)
|
||||||
{
|
{
|
||||||
d->m_reapers.append(this);
|
ProcessReaper::instance()->m_reapers.append(this);
|
||||||
|
|
||||||
m_iterationTimer.setInterval(timeoutMs);
|
m_iterationTimer.setInterval(timeoutMs);
|
||||||
m_iterationTimer.setSingleShot(true);
|
m_iterationTimer.setSingleShot(true);
|
||||||
@@ -68,7 +66,7 @@ Reaper::Reaper(QProcess *p, int timeoutMs) : m_process(p)
|
|||||||
|
|
||||||
Reaper::~Reaper()
|
Reaper::~Reaper()
|
||||||
{
|
{
|
||||||
d->m_reapers.removeOne(this);
|
ProcessReaper::instance()->m_reapers.removeOne(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
int Reaper::timeoutMs() const
|
int Reaper::timeoutMs() const
|
||||||
@@ -112,15 +110,8 @@ void Reaper::nextIteration()
|
|||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
|
|
||||||
ProcessReaper::ProcessReaper()
|
|
||||||
{
|
|
||||||
QTC_ASSERT(Internal::d == nullptr, return);
|
|
||||||
Internal::d = this;
|
|
||||||
}
|
|
||||||
|
|
||||||
ProcessReaper::~ProcessReaper()
|
ProcessReaper::~ProcessReaper()
|
||||||
{
|
{
|
||||||
QTC_ASSERT(Internal::d == this, return);
|
|
||||||
while (!m_reapers.isEmpty()) {
|
while (!m_reapers.isEmpty()) {
|
||||||
int alreadyWaited = 0;
|
int alreadyWaited = 0;
|
||||||
QList<Internal::Reaper *> toDelete;
|
QList<Internal::Reaper *> toDelete;
|
||||||
@@ -145,8 +136,6 @@ ProcessReaper::~ProcessReaper()
|
|||||||
qDeleteAll(toDelete);
|
qDeleteAll(toDelete);
|
||||||
toDelete.clear();
|
toDelete.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
Internal::d = nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProcessReaper::reap(QProcess *process, int timeoutMs)
|
void ProcessReaper::reap(QProcess *process, int timeoutMs)
|
||||||
@@ -175,8 +164,6 @@ void ProcessReaper::reap(QProcess *process, int timeoutMs)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QTC_ASSERT(Internal::d, return);
|
|
||||||
|
|
||||||
new Internal::Reaper(process, timeoutMs);
|
new Internal::Reaper(process, timeoutMs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -27,6 +27,8 @@
|
|||||||
|
|
||||||
#include "utils_global.h"
|
#include "utils_global.h"
|
||||||
|
|
||||||
|
#include "singleton.h"
|
||||||
|
|
||||||
#include <QList>
|
#include <QList>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
@@ -38,15 +40,16 @@ namespace Utils {
|
|||||||
namespace Internal { class Reaper; }
|
namespace Internal { class Reaper; }
|
||||||
|
|
||||||
class QTCREATOR_UTILS_EXPORT ProcessReaper final
|
class QTCREATOR_UTILS_EXPORT ProcessReaper final
|
||||||
|
: public SingletonWithOptionalDependencies<ProcessReaper>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ProcessReaper();
|
|
||||||
~ProcessReaper();
|
|
||||||
|
|
||||||
static void reap(QProcess *process, int timeoutMs = 500);
|
static void reap(QProcess *process, int timeoutMs = 500);
|
||||||
private:
|
private:
|
||||||
|
ProcessReaper() = default;
|
||||||
|
~ProcessReaper();
|
||||||
QList<Internal::Reaper *> m_reapers;
|
QList<Internal::Reaper *> m_reapers;
|
||||||
friend class Internal::Reaper;
|
friend class Internal::Reaper;
|
||||||
|
friend class SingletonWithOptionalDependencies<ProcessReaper>;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Utils
|
} // namespace Utils
|
||||||
|
82
src/libs/utils/singleton.cpp
Normal file
82
src/libs/utils/singleton.cpp
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2021 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "qtcassert.h"
|
||||||
|
#include "singleton.h"
|
||||||
|
|
||||||
|
#include <QCoreApplication>
|
||||||
|
#include <QList>
|
||||||
|
#include <QThread>
|
||||||
|
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
using namespace Utils;
|
||||||
|
|
||||||
|
namespace Utils {
|
||||||
|
|
||||||
|
// The order of elements reflects dependencies, i.e.
|
||||||
|
// if B requires A then B will follow A on this list
|
||||||
|
static QList<Singleton *> s_singletonList;
|
||||||
|
static QMutex s_mutex;
|
||||||
|
static std::unordered_map<std::type_index, SingletonStaticData> s_staticDataList;
|
||||||
|
|
||||||
|
Singleton::~Singleton()
|
||||||
|
{
|
||||||
|
QMutexLocker locker(&s_mutex);
|
||||||
|
s_singletonList.removeAll(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Singleton::addSingleton(Singleton *singleton)
|
||||||
|
{
|
||||||
|
QMutexLocker locker(&s_mutex);
|
||||||
|
s_singletonList.append(singleton);
|
||||||
|
}
|
||||||
|
|
||||||
|
SingletonStaticData &Singleton::staticData(std::type_index index)
|
||||||
|
{
|
||||||
|
QMutexLocker locker(&s_mutex);
|
||||||
|
return s_staticDataList[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note: it's caller responsibility to ensure that this function is being called when all other
|
||||||
|
// threads don't use any singleton. As a good practice: finish all other threads that were using
|
||||||
|
// singletons before this function is called.
|
||||||
|
// Some singletons (currently e.g. SshConnectionManager) can work only in main thread,
|
||||||
|
// so this method should be called from main thread only.
|
||||||
|
void Singleton::deleteAll()
|
||||||
|
{
|
||||||
|
QTC_ASSERT(QThread::currentThread() == qApp->thread(), return);
|
||||||
|
QList<Singleton *> oldList;
|
||||||
|
{
|
||||||
|
QMutexLocker locker(&s_mutex);
|
||||||
|
oldList = s_singletonList;
|
||||||
|
s_singletonList = {};
|
||||||
|
}
|
||||||
|
// Keep the reverse order when deleting
|
||||||
|
while (!oldList.isEmpty())
|
||||||
|
delete oldList.takeLast();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Utils
|
106
src/libs/utils/singleton.h
Normal file
106
src/libs/utils/singleton.h
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2021 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "utils_global.h"
|
||||||
|
|
||||||
|
#include <QMutex>
|
||||||
|
#include <QMutexLocker>
|
||||||
|
|
||||||
|
#include <type_traits>
|
||||||
|
#include <typeindex>
|
||||||
|
|
||||||
|
namespace Utils {
|
||||||
|
|
||||||
|
class Singleton;
|
||||||
|
|
||||||
|
struct SingletonStaticData
|
||||||
|
{
|
||||||
|
Singleton *m_instance = nullptr;
|
||||||
|
QMutex m_mutex;
|
||||||
|
};
|
||||||
|
|
||||||
|
class QTCREATOR_UTILS_EXPORT Singleton
|
||||||
|
{
|
||||||
|
Q_DISABLE_COPY_MOVE(Singleton)
|
||||||
|
public:
|
||||||
|
static void deleteAll();
|
||||||
|
|
||||||
|
private:
|
||||||
|
template <typename SingletonSubClass, typename ...Dependencies>
|
||||||
|
friend class SingletonWithOptionalDependencies;
|
||||||
|
|
||||||
|
Singleton() = default;
|
||||||
|
virtual ~Singleton();
|
||||||
|
static void addSingleton(Singleton *singleton);
|
||||||
|
static SingletonStaticData &staticData(std::type_index index);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename SingletonSubClass, typename ...Dependencies>
|
||||||
|
class SingletonWithOptionalDependencies : public Singleton
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Q_DISABLE_COPY_MOVE(SingletonWithOptionalDependencies)
|
||||||
|
static SingletonSubClass *instance()
|
||||||
|
{
|
||||||
|
SingletonStaticData &data = staticData();
|
||||||
|
QMutexLocker locker(&data.m_mutex);
|
||||||
|
if (data.m_instance == nullptr) {
|
||||||
|
// instantiate all dependencies first
|
||||||
|
if constexpr (sizeof...(Dependencies))
|
||||||
|
instantiateDependencies<Dependencies...>();
|
||||||
|
data.m_instance = new SingletonSubClass;
|
||||||
|
// put instance into static list of registered instances
|
||||||
|
addSingleton(data.m_instance);
|
||||||
|
}
|
||||||
|
return static_cast<SingletonSubClass *>(data.m_instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
SingletonWithOptionalDependencies() = default;
|
||||||
|
~SingletonWithOptionalDependencies() override
|
||||||
|
{
|
||||||
|
SingletonStaticData &data = staticData();
|
||||||
|
QMutexLocker locker(&data.m_mutex);
|
||||||
|
if (data.m_instance == this)
|
||||||
|
data.m_instance = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
template <typename ...Dependency> static void instantiateDependencies()
|
||||||
|
{
|
||||||
|
static_assert ((... && std::is_base_of_v<Singleton, Dependency>),
|
||||||
|
"All Dependencies must derive from SingletonWithOptionalDependencies class.");
|
||||||
|
(..., Dependency::instance());
|
||||||
|
}
|
||||||
|
static SingletonStaticData &staticData()
|
||||||
|
{
|
||||||
|
static SingletonStaticData &data = Singleton::staticData(std::type_index(typeid(SingletonSubClass)));
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Utils
|
@@ -143,6 +143,7 @@ SOURCES += \
|
|||||||
$$PWD/link.cpp \
|
$$PWD/link.cpp \
|
||||||
$$PWD/linecolumn.cpp \
|
$$PWD/linecolumn.cpp \
|
||||||
$$PWD/multitextcursor.cpp \
|
$$PWD/multitextcursor.cpp \
|
||||||
|
$$PWD/singleton.cpp
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
$$PWD/environmentfwd.h \
|
$$PWD/environmentfwd.h \
|
||||||
@@ -307,8 +308,9 @@ HEADERS += \
|
|||||||
$$PWD/launcherinterface.h \
|
$$PWD/launcherinterface.h \
|
||||||
$$PWD/launcherpackets.h \
|
$$PWD/launcherpackets.h \
|
||||||
$$PWD/launchersocket.h \
|
$$PWD/launchersocket.h \
|
||||||
$$PWD/qtcsettings.h
|
$$PWD/qtcsettings.h \
|
||||||
$$PWD/multitextcursor.h \
|
$$PWD/multitextcursor.h \
|
||||||
|
$$PWD/singleton.h
|
||||||
|
|
||||||
FORMS += $$PWD/filewizardpage.ui \
|
FORMS += $$PWD/filewizardpage.ui \
|
||||||
$$PWD/projectintropage.ui \
|
$$PWD/projectintropage.ui \
|
||||||
|
@@ -264,6 +264,8 @@ Project {
|
|||||||
"shellcommand.h",
|
"shellcommand.h",
|
||||||
"shellcommandpage.cpp",
|
"shellcommandpage.cpp",
|
||||||
"shellcommandpage.h",
|
"shellcommandpage.h",
|
||||||
|
"singleton.cpp",
|
||||||
|
"singleton.h",
|
||||||
"sizedarray.h",
|
"sizedarray.h",
|
||||||
"smallstring.h",
|
"smallstring.h",
|
||||||
"smallstringiterator.h",
|
"smallstringiterator.h",
|
||||||
|
@@ -27,7 +27,7 @@
|
|||||||
#include "mesoninfoparser/mesoninfoparser.h"
|
#include "mesoninfoparser/mesoninfoparser.h"
|
||||||
|
|
||||||
#include <utils/launcherinterface.h>
|
#include <utils/launcherinterface.h>
|
||||||
#include <utils/processreaper.h>
|
#include <utils/singleton.h>
|
||||||
|
|
||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
@@ -79,8 +79,7 @@ class AMesonInfoParser : public QObject
|
|||||||
private slots:
|
private slots:
|
||||||
void initTestCase()
|
void initTestCase()
|
||||||
{
|
{
|
||||||
Utils::LauncherInterface::startLauncher(
|
Utils::LauncherInterface::setPathToLauncher(qApp->applicationDirPath() + '/'
|
||||||
QCoreApplication::instance()->applicationDirPath() + '/'
|
|
||||||
+ QLatin1String(TEST_RELATIVE_LIBEXEC_PATH));
|
+ QLatin1String(TEST_RELATIVE_LIBEXEC_PATH));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,11 +120,10 @@ private slots:
|
|||||||
|
|
||||||
void cleanupTestCase()
|
void cleanupTestCase()
|
||||||
{
|
{
|
||||||
Utils::LauncherInterface::stopLauncher();
|
Utils::Singleton::deleteAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Utils::ProcessReaper processReaper;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
QTEST_MAIN(AMesonInfoParser)
|
QTEST_MAIN(AMesonInfoParser)
|
||||||
|
@@ -26,7 +26,7 @@
|
|||||||
#include "exewrappers/mesonwrapper.h"
|
#include "exewrappers/mesonwrapper.h"
|
||||||
|
|
||||||
#include <utils/launcherinterface.h>
|
#include <utils/launcherinterface.h>
|
||||||
#include <utils/processreaper.h>
|
#include <utils/singleton.h>
|
||||||
|
|
||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
@@ -50,8 +50,7 @@ class AMesonWrapper : public QObject
|
|||||||
private slots:
|
private slots:
|
||||||
void initTestCase()
|
void initTestCase()
|
||||||
{
|
{
|
||||||
Utils::LauncherInterface::startLauncher(
|
Utils::LauncherInterface::setPathToLauncher(qApp->applicationDirPath() + '/'
|
||||||
QCoreApplication::instance()->applicationDirPath() + '/'
|
|
||||||
+ QLatin1String(TEST_RELATIVE_LIBEXEC_PATH));
|
+ QLatin1String(TEST_RELATIVE_LIBEXEC_PATH));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,11 +114,10 @@ private slots:
|
|||||||
|
|
||||||
void cleanupTestCase()
|
void cleanupTestCase()
|
||||||
{
|
{
|
||||||
Utils::LauncherInterface::stopLauncher();
|
Utils::Singleton::deleteAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Utils::ProcessReaper processReaper;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
QTEST_MAIN(AMesonWrapper)
|
QTEST_MAIN(AMesonWrapper)
|
||||||
|
@@ -18,4 +18,6 @@ add_qtc_executable(qtcreator_processlauncher
|
|||||||
${UTILSDIR}/processutils.h
|
${UTILSDIR}/processutils.h
|
||||||
${UTILSDIR}/qtcassert.cpp
|
${UTILSDIR}/qtcassert.cpp
|
||||||
${UTILSDIR}/qtcassert.h
|
${UTILSDIR}/qtcassert.h
|
||||||
|
${UTILSDIR}/singleton.cpp
|
||||||
|
${UTILSDIR}/singleton.h
|
||||||
)
|
)
|
||||||
|
@@ -25,9 +25,10 @@
|
|||||||
|
|
||||||
#include "launcherlogging.h"
|
#include "launcherlogging.h"
|
||||||
#include "launchersockethandler.h"
|
#include "launchersockethandler.h"
|
||||||
#include "processreaper.h"
|
#include "singleton.h"
|
||||||
|
|
||||||
#include <QtCore/qcoreapplication.h>
|
#include <QtCore/qcoreapplication.h>
|
||||||
|
#include <QtCore/qscopeguard.h>
|
||||||
#include <QtCore/qtimer.h>
|
#include <QtCore/qtimer.h>
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
@@ -52,7 +53,8 @@ int main(int argc, char *argv[])
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
Utils::ProcessReaper processReaper;
|
auto cleanup = qScopeGuard([] { Utils::Singleton::deleteAll(); });
|
||||||
|
|
||||||
Utils::Internal::LauncherSocketHandler launcher(app.arguments().constLast());
|
Utils::Internal::LauncherSocketHandler launcher(app.arguments().constLast());
|
||||||
QTimer::singleShot(0, &launcher, &Utils::Internal::LauncherSocketHandler::start);
|
QTimer::singleShot(0, &launcher, &Utils::Internal::LauncherSocketHandler::start);
|
||||||
return app.exec();
|
return app.exec();
|
||||||
|
@@ -7,6 +7,8 @@ QT = core network
|
|||||||
|
|
||||||
UTILS_DIR = $$PWD/../../libs/utils
|
UTILS_DIR = $$PWD/../../libs/utils
|
||||||
|
|
||||||
|
DEFINES *= QTCREATOR_UTILS_STATIC_LIB
|
||||||
|
|
||||||
INCLUDEPATH += $$UTILS_DIR
|
INCLUDEPATH += $$UTILS_DIR
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
@@ -15,7 +17,8 @@ HEADERS += \
|
|||||||
$$UTILS_DIR/launcherpackets.h \
|
$$UTILS_DIR/launcherpackets.h \
|
||||||
$$UTILS_DIR/processreaper.h \
|
$$UTILS_DIR/processreaper.h \
|
||||||
$$UTILS_DIR/processutils.h \
|
$$UTILS_DIR/processutils.h \
|
||||||
$$UTILS_DIR/qtcassert.h
|
$$UTILS_DIR/qtcassert.h \
|
||||||
|
$$UTILS_DIR/singleton.h
|
||||||
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
launcherlogging.cpp \
|
launcherlogging.cpp \
|
||||||
@@ -24,4 +27,5 @@ SOURCES += \
|
|||||||
$$UTILS_DIR/launcherpackets.cpp \
|
$$UTILS_DIR/launcherpackets.cpp \
|
||||||
$$UTILS_DIR/processreaper.cpp \
|
$$UTILS_DIR/processreaper.cpp \
|
||||||
$$UTILS_DIR/processutils.cpp \
|
$$UTILS_DIR/processutils.cpp \
|
||||||
$$UTILS_DIR/qtcassert.cpp
|
$$UTILS_DIR/qtcassert.cpp \
|
||||||
|
$$UTILS_DIR/singleton.cpp
|
||||||
|
@@ -30,6 +30,8 @@ QtcTool {
|
|||||||
"processutils.h",
|
"processutils.h",
|
||||||
"qtcassert.cpp",
|
"qtcassert.cpp",
|
||||||
"qtcassert.h",
|
"qtcassert.h",
|
||||||
|
"singleton.cpp",
|
||||||
|
"singleton.h",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -26,15 +26,14 @@
|
|||||||
#include <ssh/sftpsession.h>
|
#include <ssh/sftpsession.h>
|
||||||
#include <ssh/sftptransfer.h>
|
#include <ssh/sftptransfer.h>
|
||||||
#include <ssh/sshconnection.h>
|
#include <ssh/sshconnection.h>
|
||||||
#include <ssh/sshconnectionmanager.h>
|
|
||||||
#include <ssh/sshremoteprocessrunner.h>
|
#include <ssh/sshremoteprocessrunner.h>
|
||||||
#include <ssh/sshsettings.h>
|
#include <ssh/sshsettings.h>
|
||||||
|
|
||||||
#include <utils/algorithm.h>
|
#include <utils/algorithm.h>
|
||||||
#include <utils/environment.h>
|
#include <utils/environment.h>
|
||||||
#include <utils/launcherinterface.h>
|
#include <utils/launcherinterface.h>
|
||||||
#include <utils/processreaper.h>
|
|
||||||
#include <utils/qtcprocess.h>
|
#include <utils/qtcprocess.h>
|
||||||
|
#include <utils/singleton.h>
|
||||||
#include <utils/temporarydirectory.h>
|
#include <utils/temporarydirectory.h>
|
||||||
|
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
@@ -134,17 +133,12 @@ private slots:
|
|||||||
void cleanupTestCase();
|
void cleanupTestCase();
|
||||||
private:
|
private:
|
||||||
bool waitForConnection(SshConnection &connection);
|
bool waitForConnection(SshConnection &connection);
|
||||||
|
|
||||||
Utils::ProcessReaper *processReaper = nullptr;
|
|
||||||
SshConnectionManager *sshConnectionManager = nullptr;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void tst_Ssh::initTestCase()
|
void tst_Ssh::initTestCase()
|
||||||
{
|
{
|
||||||
processReaper = new Utils::ProcessReaper();
|
Utils::LauncherInterface::setPathToLauncher(qApp->applicationDirPath() + '/'
|
||||||
Utils::LauncherInterface::startLauncher(qApp->applicationDirPath() + '/'
|
|
||||||
+ QLatin1String(TEST_RELATIVE_LIBEXEC_PATH));
|
+ QLatin1String(TEST_RELATIVE_LIBEXEC_PATH));
|
||||||
sshConnectionManager = new SshConnectionManager();
|
|
||||||
Utils::TemporaryDirectory::setMasterTemporaryDirectory(QDir::tempPath()
|
Utils::TemporaryDirectory::setMasterTemporaryDirectory(QDir::tempPath()
|
||||||
+ "/qtc-ssh-autotest-XXXXXX");
|
+ "/qtc-ssh-autotest-XXXXXX");
|
||||||
}
|
}
|
||||||
@@ -647,9 +641,7 @@ void tst_Ssh::sftp()
|
|||||||
|
|
||||||
void tst_Ssh::cleanupTestCase()
|
void tst_Ssh::cleanupTestCase()
|
||||||
{
|
{
|
||||||
delete sshConnectionManager;
|
Utils::Singleton::deleteAll();
|
||||||
Utils::LauncherInterface::stopLauncher();
|
|
||||||
delete processReaper;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool tst_Ssh::waitForConnection(SshConnection &connection)
|
bool tst_Ssh::waitForConnection(SshConnection &connection)
|
||||||
|
@@ -27,8 +27,8 @@
|
|||||||
#include <utils/hostosinfo.h>
|
#include <utils/hostosinfo.h>
|
||||||
#include <utils/launcherinterface.h>
|
#include <utils/launcherinterface.h>
|
||||||
#include <utils/porting.h>
|
#include <utils/porting.h>
|
||||||
#include <utils/processreaper.h>
|
|
||||||
#include <utils/qtcprocess.h>
|
#include <utils/qtcprocess.h>
|
||||||
|
#include <utils/singleton.h>
|
||||||
#include <utils/stringutils.h>
|
#include <utils/stringutils.h>
|
||||||
|
|
||||||
#include <QElapsedTimer>
|
#include <QElapsedTimer>
|
||||||
@@ -213,7 +213,6 @@ private slots:
|
|||||||
private:
|
private:
|
||||||
void iteratorEditsHelper(OsType osType);
|
void iteratorEditsHelper(OsType osType);
|
||||||
|
|
||||||
Utils::ProcessReaper processReaper;
|
|
||||||
Environment envWindows;
|
Environment envWindows;
|
||||||
Environment envLinux;
|
Environment envLinux;
|
||||||
|
|
||||||
@@ -225,7 +224,7 @@ private:
|
|||||||
|
|
||||||
void tst_QtcProcess::initTestCase()
|
void tst_QtcProcess::initTestCase()
|
||||||
{
|
{
|
||||||
Utils::LauncherInterface::startLauncher(qApp->applicationDirPath() + '/'
|
Utils::LauncherInterface::setPathToLauncher(qApp->applicationDirPath() + '/'
|
||||||
+ QLatin1String(TEST_RELATIVE_LIBEXEC_PATH));
|
+ QLatin1String(TEST_RELATIVE_LIBEXEC_PATH));
|
||||||
if (qEnvironmentVariableIsSet(kExitCodeSubProcessCode))
|
if (qEnvironmentVariableIsSet(kExitCodeSubProcessCode))
|
||||||
exitCodeSubProcessMain();
|
exitCodeSubProcessMain();
|
||||||
@@ -285,7 +284,7 @@ void tst_QtcProcess::initTestCase()
|
|||||||
|
|
||||||
void tst_QtcProcess::cleanupTestCase()
|
void tst_QtcProcess::cleanupTestCase()
|
||||||
{
|
{
|
||||||
Utils::LauncherInterface::stopLauncher();
|
Utils::Singleton::deleteAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(ProcessArgs::SplitError)
|
Q_DECLARE_METATYPE(ProcessArgs::SplitError)
|
||||||
|
@@ -30,7 +30,7 @@
|
|||||||
|
|
||||||
#include <sqliteglobal.h>
|
#include <sqliteglobal.h>
|
||||||
#include <utils/launcherinterface.h>
|
#include <utils/launcherinterface.h>
|
||||||
#include <utils/processreaper.h>
|
#include <utils/singleton.h>
|
||||||
#include <utils/temporarydirectory.h>
|
#include <utils/temporarydirectory.h>
|
||||||
|
|
||||||
#include <QGuiApplication>
|
#include <QGuiApplication>
|
||||||
@@ -61,10 +61,8 @@ int main(int argc, char *argv[])
|
|||||||
Sqlite::Database::activateLogging();
|
Sqlite::Database::activateLogging();
|
||||||
|
|
||||||
QGuiApplication application(argc, argv);
|
QGuiApplication application(argc, argv);
|
||||||
Utils::ProcessReaper processReaper;
|
Utils::LauncherInterface::setPathToLauncher(qApp->applicationDirPath() + '/'
|
||||||
Utils::LauncherInterface::startLauncher(qApp->applicationDirPath() + '/'
|
|
||||||
+ QLatin1String(TEST_RELATIVE_LIBEXEC_PATH));
|
+ QLatin1String(TEST_RELATIVE_LIBEXEC_PATH));
|
||||||
auto cleanup = qScopeGuard([] { Utils::LauncherInterface::stopLauncher(); });
|
|
||||||
testing::InitGoogleTest(&argc, argv);
|
testing::InitGoogleTest(&argc, argv);
|
||||||
#ifdef WITH_BENCHMARKS
|
#ifdef WITH_BENCHMARKS
|
||||||
benchmark::Initialize(&argc, argv);
|
benchmark::Initialize(&argc, argv);
|
||||||
@@ -75,6 +73,7 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
int testsHaveErrors = RUN_ALL_TESTS();
|
int testsHaveErrors = RUN_ALL_TESTS();
|
||||||
|
|
||||||
|
Utils::Singleton::deleteAll();
|
||||||
#ifdef WITH_BENCHMARKS
|
#ifdef WITH_BENCHMARKS
|
||||||
if (testsHaveErrors == 0 && application.arguments().contains(QStringLiteral("--with-benchmarks")))
|
if (testsHaveErrors == 0 && application.arguments().contains(QStringLiteral("--with-benchmarks")))
|
||||||
benchmark::RunSpecifiedBenchmarks();
|
benchmark::RunSpecifiedBenchmarks();
|
||||||
|
Reference in New Issue
Block a user