mirror of
https://github.com/swift-project/pilotclient.git
synced 2026-04-28 11:45:40 +08:00
[skip ci] refactor: Use composition for update timer
The timer is not required by all classes and the deep inheritance makes it hard to see where it is actually used. Use composition instead
This commit is contained in:
@@ -52,8 +52,6 @@ namespace swift::core::afv::clients
|
|||||||
connect(m_connection, &CClientConnection::audioReceived, this, &CAfvClient::audioOutDataAvailable);
|
connect(m_connection, &CClientConnection::audioReceived, this, &CAfvClient::audioOutDataAvailable);
|
||||||
connect(m_voiceServerTimer, &QTimer::timeout, this, &CAfvClient::onTimerUpdate);
|
connect(m_voiceServerTimer, &QTimer::timeout, this, &CAfvClient::onTimerUpdate);
|
||||||
|
|
||||||
m_updateTimer.stop(); // not used
|
|
||||||
|
|
||||||
// deferred init - use swift::misc:: singleShot to call in correct thread, "myself" NOT needed
|
// deferred init - use swift::misc:: singleShot to call in correct thread, "myself" NOT needed
|
||||||
swift::misc::singleShot(1000, this, [=] { this->deferredInit(); });
|
swift::misc::singleShot(1000, this, [=] { this->deferredInit(); });
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,20 +27,22 @@ using namespace swift::misc::physical_quantities;
|
|||||||
using namespace swift::misc::simulation;
|
using namespace swift::misc::simulation;
|
||||||
using namespace swift::core::fsd;
|
using namespace swift::core::fsd;
|
||||||
|
|
||||||
|
static constexpr std::chrono::milliseconds updateInterval { 7500 };
|
||||||
|
|
||||||
namespace swift::core
|
namespace swift::core
|
||||||
{
|
{
|
||||||
CAirspaceAnalyzer::CAirspaceAnalyzer(IOwnAircraftProvider *ownAircraftProvider, CFSDClient *fsdClient,
|
CAirspaceAnalyzer::CAirspaceAnalyzer(IOwnAircraftProvider *ownAircraftProvider, CFSDClient *fsdClient,
|
||||||
CAirspaceMonitor *airspaceMonitorParent)
|
CAirspaceMonitor *airspaceMonitorParent)
|
||||||
: CContinuousWorker(airspaceMonitorParent, "CAirspaceAnalyzer"), COwnAircraftAware(ownAircraftProvider),
|
: CContinuousWorker(airspaceMonitorParent, "CAirspaceAnalyzer"), COwnAircraftAware(ownAircraftProvider),
|
||||||
CRemoteAircraftAware(airspaceMonitorParent)
|
CRemoteAircraftAware(airspaceMonitorParent), m_updateTimer(airspaceMonitorParent, "CAirspaceAnalyzer")
|
||||||
{
|
{
|
||||||
Q_ASSERT_X(fsdClient, Q_FUNC_INFO, "Network object required to connect");
|
Q_ASSERT_X(fsdClient, Q_FUNC_INFO, "Network object required to connect");
|
||||||
|
|
||||||
// all in new thread from here on
|
// all in new thread from here on
|
||||||
this->setObjectName(this->getName());
|
this->setObjectName(this->getName());
|
||||||
m_updateTimer.start(7500);
|
m_updateTimer.startTimer(updateInterval);
|
||||||
m_lastWatchdogCallMsSinceEpoch = QDateTime::currentMSecsSinceEpoch();
|
m_lastWatchdogCallMsSinceEpoch = QDateTime::currentMSecsSinceEpoch();
|
||||||
bool c = connect(&m_updateTimer, &QTimer::timeout, this, &CAirspaceAnalyzer::onTimeout);
|
bool c = connect(&m_updateTimer, &CThreadedTimer::timeout, this, &CAirspaceAnalyzer::onTimeout);
|
||||||
Q_ASSERT(c);
|
Q_ASSERT(c);
|
||||||
|
|
||||||
// network connected
|
// network connected
|
||||||
@@ -134,9 +136,9 @@ namespace swift::core
|
|||||||
if (newStatus.isDisconnected())
|
if (newStatus.isDisconnected())
|
||||||
{
|
{
|
||||||
this->clear();
|
this->clear();
|
||||||
m_updateTimer.stop();
|
m_updateTimer.stopTimer();
|
||||||
}
|
}
|
||||||
else if (newStatus.isConnected()) { m_updateTimer.start(); }
|
else if (newStatus.isConnected()) { m_updateTimer.startTimer(updateInterval); }
|
||||||
}
|
}
|
||||||
|
|
||||||
void CAirspaceAnalyzer::onTimeout()
|
void CAirspaceAnalyzer::onTimeout()
|
||||||
@@ -170,7 +172,7 @@ namespace swift::core
|
|||||||
// this is a trick to not remove everything while debugging
|
// this is a trick to not remove everything while debugging
|
||||||
const qint64 currentTimeMsEpoch = QDateTime::currentMSecsSinceEpoch();
|
const qint64 currentTimeMsEpoch = QDateTime::currentMSecsSinceEpoch();
|
||||||
const qint64 callDiffMs = currentTimeMsEpoch - m_lastWatchdogCallMsSinceEpoch;
|
const qint64 callDiffMs = currentTimeMsEpoch - m_lastWatchdogCallMsSinceEpoch;
|
||||||
const qint64 callThresholdMs = static_cast<qint64>(m_updateTimer.interval() * 1.5);
|
const qint64 callThresholdMs = static_cast<qint64>(updateInterval.count() * 1.5);
|
||||||
m_lastWatchdogCallMsSinceEpoch = currentTimeMsEpoch;
|
m_lastWatchdogCallMsSinceEpoch = currentTimeMsEpoch;
|
||||||
if (callDiffMs > callThresholdMs)
|
if (callDiffMs > callThresholdMs)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
#include "misc/simulation/airspaceaircraftsnapshot.h"
|
#include "misc/simulation/airspaceaircraftsnapshot.h"
|
||||||
#include "misc/simulation/ownaircraftprovider.h"
|
#include "misc/simulation/ownaircraftprovider.h"
|
||||||
#include "misc/simulation/remoteaircraftprovider.h"
|
#include "misc/simulation/remoteaircraftprovider.h"
|
||||||
|
#include "misc/threadedtimer.h"
|
||||||
#include "misc/worker.h"
|
#include "misc/worker.h"
|
||||||
|
|
||||||
namespace swift::misc::aviation
|
namespace swift::misc::aviation
|
||||||
@@ -134,6 +135,7 @@ namespace swift::core
|
|||||||
qint64 m_lastWatchdogCallMsSinceEpoch; //!< when last called
|
qint64 m_lastWatchdogCallMsSinceEpoch; //!< when last called
|
||||||
qint64 m_doNotRunAgainBefore = -1; //!< do not run again before, also used to detect debugging
|
qint64 m_doNotRunAgainBefore = -1; //!< do not run again before, also used to detect debugging
|
||||||
std::atomic_bool m_enabledWatchdog { true }; //!< watchdog enabled
|
std::atomic_bool m_enabledWatchdog { true }; //!< watchdog enabled
|
||||||
|
misc::CThreadedTimer m_updateTimer; //!< Thread safe timer for update timeout
|
||||||
|
|
||||||
// snapshot
|
// snapshot
|
||||||
swift::misc::simulation::CAirspaceAircraftSnapshot m_latestAircraftSnapshot;
|
swift::misc::simulation::CAirspaceAircraftSnapshot m_latestAircraftSnapshot;
|
||||||
|
|||||||
@@ -90,7 +90,8 @@ namespace swift::core::context
|
|||||||
Qt::QueuedConnection);
|
Qt::QueuedConnection);
|
||||||
|
|
||||||
m_validator->start(QThread::LowestPriority);
|
m_validator->start(QThread::LowestPriority);
|
||||||
m_validator->startUpdating(60);
|
using namespace std::chrono_literals;
|
||||||
|
m_validator->startUpdating(60s);
|
||||||
}
|
}
|
||||||
|
|
||||||
// For validation we need simulator directory and model directory
|
// For validation we need simulator directory and model directory
|
||||||
|
|||||||
@@ -30,9 +30,10 @@ namespace swift::core::db
|
|||||||
return cats;
|
return cats;
|
||||||
}
|
}
|
||||||
|
|
||||||
CBackgroundDataUpdater::CBackgroundDataUpdater(QObject *owner) : CContinuousWorker(owner, "Background data updater")
|
CBackgroundDataUpdater::CBackgroundDataUpdater(QObject *owner)
|
||||||
|
: CContinuousWorker(owner, "Background data updater"), m_updateTimer(owner, "Background data updater")
|
||||||
{
|
{
|
||||||
connect(&m_updateTimer, &QTimer::timeout, this, &CBackgroundDataUpdater::doWork);
|
connect(&m_updateTimer, &misc::CThreadedTimer::timeout, this, &CBackgroundDataUpdater::doWork);
|
||||||
if (sApp && sApp->hasWebDataServices())
|
if (sApp && sApp->hasWebDataServices())
|
||||||
{
|
{
|
||||||
connect(sApp->getWebDataServices()->getDatabaseWriter(), &CDatabaseWriter::publishedModelsSimplified, this,
|
connect(sApp->getWebDataServices()->getDatabaseWriter(), &CDatabaseWriter::publishedModelsSimplified, this,
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
#include "misc/network/entityflags.h"
|
#include "misc/network/entityflags.h"
|
||||||
#include "misc/simulation/data/modelcaches.h"
|
#include "misc/simulation/data/modelcaches.h"
|
||||||
#include "misc/statusmessagelist.h"
|
#include "misc/statusmessagelist.h"
|
||||||
|
#include "misc/threadedtimer.h"
|
||||||
#include "misc/worker.h"
|
#include "misc/worker.h"
|
||||||
|
|
||||||
namespace swift::core::db
|
namespace swift::core::db
|
||||||
@@ -47,6 +48,7 @@ namespace swift::core::db
|
|||||||
std::atomic_bool m_updatePublishedModels { true }; //!< update when models have been updated
|
std::atomic_bool m_updatePublishedModels { true }; //!< update when models have been updated
|
||||||
QMap<QString, QDateTime> m_syncedModelsLatestChange; //! timestamp per cache when last synced
|
QMap<QString, QDateTime> m_syncedModelsLatestChange; //! timestamp per cache when last synced
|
||||||
swift::misc::CStatusMessageList m_messageHistory;
|
swift::misc::CStatusMessageList m_messageHistory;
|
||||||
|
misc::CThreadedTimer m_updateTimer; //!< Thread safe timer for update timeout
|
||||||
|
|
||||||
// set/caches as member as we are in own thread, central instance will not work
|
// set/caches as member as we are in own thread, central instance will not work
|
||||||
swift::misc::simulation::data::CModelCaches m_modelCaches { false, this };
|
swift::misc::simulation::data::CModelCaches m_modelCaches { false, this };
|
||||||
|
|||||||
@@ -5,40 +5,33 @@
|
|||||||
|
|
||||||
namespace swift::core
|
namespace swift::core
|
||||||
{
|
{
|
||||||
CThreadedReaderPeriodic::CThreadedReaderPeriodic(QObject *owner, const QString &name) : CThreadedReader(owner, name)
|
CThreadedReaderPeriodic::CThreadedReaderPeriodic(QObject *owner, const QString &name)
|
||||||
|
: CThreadedReader(owner, name), m_updateTimer(owner, name, true)
|
||||||
{
|
{
|
||||||
connect(&m_updateTimer, &QTimer::timeout, this, &CThreadedReaderPeriodic::doWork);
|
connect(&m_updateTimer, &misc::CThreadedTimer::timeout, this, &CThreadedReaderPeriodic::doWork);
|
||||||
m_updateTimer.setSingleShot(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CThreadedReaderPeriodic::startReader()
|
void CThreadedReaderPeriodic::startReader()
|
||||||
{
|
{
|
||||||
Q_ASSERT_X(hasStarted(), Q_FUNC_INFO, "Thread was not started yet!");
|
Q_ASSERT_X(hasStarted(), Q_FUNC_INFO, "Thread was not started yet!");
|
||||||
Q_ASSERT(m_initialTime > 0);
|
QTimer::singleShot(m_initialTime.load(), this, [=] { this->doWork(); });
|
||||||
QTimer::singleShot(m_initialTime, this, [=] { this->doWork(); });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CThreadedReaderPeriodic::setInitialAndPeriodicTime(int initialTime, int periodicTime)
|
void CThreadedReaderPeriodic::setInitialAndPeriodicTime(std::chrono::milliseconds initialTime,
|
||||||
|
std::chrono::milliseconds periodicTime)
|
||||||
{
|
{
|
||||||
m_initialTime = initialTime;
|
m_initialTime = initialTime;
|
||||||
m_periodicTime = periodicTime;
|
m_periodicTime = periodicTime;
|
||||||
|
|
||||||
// if timer is active start with delta time
|
|
||||||
// remark: will be reset in doWork
|
|
||||||
if (m_updateTimer.isActive())
|
|
||||||
{
|
|
||||||
const int oldPeriodicTime = m_updateTimer.interval();
|
|
||||||
const int delta = m_periodicTime - oldPeriodicTime + m_updateTimer.remainingTime();
|
|
||||||
m_updateTimer.start(qMax(delta, 0));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CThreadedReaderPeriodic::doWork()
|
void CThreadedReaderPeriodic::doWork()
|
||||||
{
|
{
|
||||||
if (!doWorkCheck()) { return; }
|
if (!doWorkCheck()) { return; }
|
||||||
this->doWorkImpl();
|
this->doWorkImpl();
|
||||||
Q_ASSERT(m_periodicTime > 0);
|
using namespace std::chrono_literals;
|
||||||
m_updateTimer.start(m_periodicTime); // restart
|
Q_ASSERT(m_periodicTime.load() > 0ms);
|
||||||
|
|
||||||
|
m_updateTimer.startTimer(m_periodicTime); // restart
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace swift::core
|
} // namespace swift::core
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
#include "core/swiftcoreexport.h"
|
#include "core/swiftcoreexport.h"
|
||||||
#include "core/threadedreader.h"
|
#include "core/threadedreader.h"
|
||||||
|
#include "misc/threadedtimer.h"
|
||||||
|
|
||||||
namespace swift::core
|
namespace swift::core
|
||||||
{
|
{
|
||||||
@@ -34,14 +35,18 @@ namespace swift::core
|
|||||||
virtual void doWorkImpl() = 0;
|
virtual void doWorkImpl() = 0;
|
||||||
|
|
||||||
//! Set initial and periodic times
|
//! Set initial and periodic times
|
||||||
void setInitialAndPeriodicTime(int initialTime, int periodicTime);
|
//! Changes only apply after the next time the timer restarts
|
||||||
|
//! \threadsafe
|
||||||
|
void setInitialAndPeriodicTime(std::chrono::milliseconds initialTime, std::chrono::milliseconds periodicTime);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
//! Trigger doWorkImpl
|
//! Trigger doWorkImpl
|
||||||
void doWork();
|
void doWork();
|
||||||
|
|
||||||
int m_initialTime = -1; //!< Initial start delay
|
std::atomic<std::chrono::milliseconds> m_initialTime = std::chrono::milliseconds(0); //!< Initial start delay
|
||||||
int m_periodicTime = -1; //!< Periodic time after which the task is repeated
|
std::atomic<std::chrono::milliseconds> m_periodicTime = std::chrono::milliseconds(0); //!< Periodic time after which the task is repeated
|
||||||
|
|
||||||
|
misc::CThreadedTimer m_updateTimer; //!< Update timer
|
||||||
};
|
};
|
||||||
} // namespace swift::core
|
} // namespace swift::core
|
||||||
|
|
||||||
|
|||||||
@@ -317,6 +317,7 @@ namespace swift::core::vatsim
|
|||||||
void CVatsimDataFileReader::reloadSettings()
|
void CVatsimDataFileReader::reloadSettings()
|
||||||
{
|
{
|
||||||
CReaderSettings s = m_settings.get();
|
CReaderSettings s = m_settings.get();
|
||||||
setInitialAndPeriodicTime(s.getInitialTime().toMs(), s.getPeriodicTime().toMs());
|
setInitialAndPeriodicTime(std::chrono::milliseconds(s.getInitialTime().toMs()),
|
||||||
|
std::chrono::milliseconds(s.getPeriodicTime().toMs()));
|
||||||
}
|
}
|
||||||
} // namespace swift::core::vatsim
|
} // namespace swift::core::vatsim
|
||||||
|
|||||||
@@ -131,6 +131,7 @@ namespace swift::core::vatsim
|
|||||||
void CVatsimMetarReader::reloadSettings()
|
void CVatsimMetarReader::reloadSettings()
|
||||||
{
|
{
|
||||||
const CReaderSettings s = m_settings.get();
|
const CReaderSettings s = m_settings.get();
|
||||||
this->setInitialAndPeriodicTime(s.getInitialTime().toMs(), s.getPeriodicTime().toMs());
|
this->setInitialAndPeriodicTime(std::chrono::milliseconds(s.getInitialTime().toMs()),
|
||||||
|
std::chrono::milliseconds(s.getPeriodicTime().toMs()));
|
||||||
}
|
}
|
||||||
} // namespace swift::core::vatsim
|
} // namespace swift::core::vatsim
|
||||||
|
|||||||
@@ -319,6 +319,8 @@ add_library(misc SHARED
|
|||||||
swiftdirectories.cpp
|
swiftdirectories.cpp
|
||||||
swiftdirectories.h
|
swiftdirectories.h
|
||||||
swiftmiscexport.h
|
swiftmiscexport.h
|
||||||
|
threadedtimer.cpp
|
||||||
|
threadedtimer.h
|
||||||
threadutils.cpp
|
threadutils.cpp
|
||||||
threadutils.h
|
threadutils.h
|
||||||
timestampbased.cpp
|
timestampbased.cpp
|
||||||
|
|||||||
@@ -22,9 +22,10 @@ namespace swift::misc::simulation
|
|||||||
return cats;
|
return cats;
|
||||||
}
|
}
|
||||||
|
|
||||||
CBackgroundValidation::CBackgroundValidation(QObject *owner) : CContinuousWorker(owner, "Background validation")
|
CBackgroundValidation::CBackgroundValidation(QObject *owner)
|
||||||
|
: CContinuousWorker(owner, "Background validation"), m_updateTimer(owner, "Background validation")
|
||||||
{
|
{
|
||||||
connect(&m_updateTimer, &QTimer::timeout, this, &CBackgroundValidation::doWork);
|
connect(&m_updateTimer, &CThreadedTimer::timeout, this, &CBackgroundValidation::doWork);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CBackgroundValidation::setCurrentSimulator(const CSimulatorInfo &simulator, const QString &simDirectory,
|
void CBackgroundValidation::setCurrentSimulator(const CSimulatorInfo &simulator, const QString &simDirectory,
|
||||||
@@ -94,10 +95,17 @@ namespace swift::misc::simulation
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CBackgroundValidation::startUpdating(std::chrono::milliseconds ms)
|
||||||
|
{
|
||||||
|
Q_ASSERT_X(this->hasStarted(), Q_FUNC_INFO, "Worker not started yet");
|
||||||
|
m_updateTimer.startTimer(ms);
|
||||||
|
setEnabled(true);
|
||||||
|
}
|
||||||
|
|
||||||
void CBackgroundValidation::beforeQuit() noexcept
|
void CBackgroundValidation::beforeQuit() noexcept
|
||||||
{
|
{
|
||||||
m_wasStopped = true; // stop in utility functions
|
m_wasStopped = true; // stop in utility functions
|
||||||
this->stopUpdateTimer();
|
m_updateTimer.stopTimer();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CBackgroundValidation::doWork()
|
void CBackgroundValidation::doWork()
|
||||||
@@ -162,7 +170,7 @@ namespace swift::misc::simulation
|
|||||||
m_timerBasedRuns++;
|
m_timerBasedRuns++;
|
||||||
|
|
||||||
// stop timer after some runs
|
// stop timer after some runs
|
||||||
if (m_timerBasedRuns > 3) { m_updateTimer.stop(); }
|
if (m_timerBasedRuns > 3) { m_updateTimer.stopTimer(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
emit this->validating(false);
|
emit this->validating(false);
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
#include "misc/simulation/settings/modelmatchersettings.h"
|
#include "misc/simulation/settings/modelmatchersettings.h"
|
||||||
#include "misc/statusmessagelist.h"
|
#include "misc/statusmessagelist.h"
|
||||||
#include "misc/swiftmiscexport.h"
|
#include "misc/swiftmiscexport.h"
|
||||||
|
#include "misc/threadedtimer.h"
|
||||||
#include "misc/worker.h"
|
#include "misc/worker.h"
|
||||||
|
|
||||||
namespace swift::misc::simulation
|
namespace swift::misc::simulation
|
||||||
@@ -63,6 +64,10 @@ namespace swift::misc::simulation
|
|||||||
//! \threadsafe
|
//! \threadsafe
|
||||||
bool requestLastValidationResults();
|
bool requestLastValidationResults();
|
||||||
|
|
||||||
|
//! Start the updating timer
|
||||||
|
//! \threadsafe
|
||||||
|
void startUpdating(std::chrono::milliseconds ms);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
//! Validating
|
//! Validating
|
||||||
void validating(bool running);
|
void validating(bool running);
|
||||||
@@ -96,6 +101,8 @@ namespace swift::misc::simulation
|
|||||||
// Set/caches as member as we are in own thread, central instance will not work
|
// Set/caches as member as we are in own thread, central instance will not work
|
||||||
data::CModelSetCaches m_modelSets { false, this };
|
data::CModelSetCaches m_modelSets { false, this };
|
||||||
|
|
||||||
|
CThreadedTimer m_updateTimer; //!< update timer
|
||||||
|
|
||||||
//! Do the validation checks
|
//! Do the validation checks
|
||||||
void doWork();
|
void doWork();
|
||||||
};
|
};
|
||||||
|
|||||||
52
src/misc/threadedtimer.cpp
Normal file
52
src/misc/threadedtimer.cpp
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright (C) 2025 swift Project Community / Contributors
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-swift-pilot-client-1
|
||||||
|
|
||||||
|
#include "misc/threadedtimer.h"
|
||||||
|
|
||||||
|
#include <QPointer>
|
||||||
|
|
||||||
|
#include "threadutils.h"
|
||||||
|
|
||||||
|
namespace swift::misc
|
||||||
|
{
|
||||||
|
CThreadedTimer::CThreadedTimer(QObject *owner, const QString &name, bool singleShot) : QObject(owner)
|
||||||
|
{
|
||||||
|
m_updateTimer.setObjectName(name + ":timer");
|
||||||
|
m_updateTimer.setSingleShot(singleShot);
|
||||||
|
connect(&m_updateTimer, &QTimer::timeout, this, &CThreadedTimer::timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CThreadedTimer::startTimer(std::chrono::milliseconds ms)
|
||||||
|
{
|
||||||
|
if (!CThreadUtils::isInThisThread(this))
|
||||||
|
{
|
||||||
|
// shift in correct thread
|
||||||
|
QPointer<CThreadedTimer> myself(this);
|
||||||
|
QTimer::singleShot(0, this, [=] {
|
||||||
|
if (!myself) { return; }
|
||||||
|
this->startTimer(ms);
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
connect(thread(), &QThread::finished, &m_updateTimer, &QTimer::stop, Qt::UniqueConnection);
|
||||||
|
m_updateTimer.start(ms);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CThreadedTimer::stopTimer()
|
||||||
|
{
|
||||||
|
if (!CThreadUtils::isInThisThread(this))
|
||||||
|
{
|
||||||
|
// shift in correct thread
|
||||||
|
QPointer<CThreadedTimer> myself(this);
|
||||||
|
QTimer::singleShot(0, this, [=] {
|
||||||
|
if (!myself) { return; }
|
||||||
|
this->stopTimer();
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_updateTimer.isActive()) { return; }
|
||||||
|
m_updateTimer.stop();
|
||||||
|
}
|
||||||
|
} // namespace swift::misc
|
||||||
42
src/misc/threadedtimer.h
Normal file
42
src/misc/threadedtimer.h
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright (C) 2025 swift Project Community / Contributors
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-swift-pilot-client-1
|
||||||
|
|
||||||
|
//! \file
|
||||||
|
|
||||||
|
#ifndef SWIFT_MISC_THREADED_TIMER_H
|
||||||
|
#define SWIFT_MISC_THREADED_TIMER_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QTimer>
|
||||||
|
|
||||||
|
#include "misc/swiftmiscexport.h"
|
||||||
|
|
||||||
|
namespace swift::misc
|
||||||
|
{
|
||||||
|
//! Thread-safe timer class
|
||||||
|
class SWIFT_MISC_EXPORT CThreadedTimer : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
CThreadedTimer(QObject *owner, const QString& name, bool singleShot = false);
|
||||||
|
|
||||||
|
//! Destructor
|
||||||
|
~CThreadedTimer() override = default;
|
||||||
|
|
||||||
|
//! Start updating (start timer)
|
||||||
|
//! \threadsafe
|
||||||
|
void startTimer(std::chrono::milliseconds ms);
|
||||||
|
|
||||||
|
//! Safely stop update time
|
||||||
|
//! \threadsafe
|
||||||
|
void stopTimer();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void timeout();
|
||||||
|
|
||||||
|
private:
|
||||||
|
QTimer m_updateTimer { this }; //!< timer which can be used by implementing classes
|
||||||
|
};
|
||||||
|
} // namespace swift::misc
|
||||||
|
|
||||||
|
#endif // SWIFT_MISC_THREADED_TIMER_H
|
||||||
@@ -160,7 +160,6 @@ namespace swift::misc
|
|||||||
{
|
{
|
||||||
Q_ASSERT_X(!name.isEmpty(), Q_FUNC_INFO, "Empty name");
|
Q_ASSERT_X(!name.isEmpty(), Q_FUNC_INFO, "Empty name");
|
||||||
this->setObjectName(m_name);
|
this->setObjectName(m_name);
|
||||||
m_updateTimer.setObjectName(m_name + ":timer");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CContinuousWorker::start(QThread::Priority priority)
|
void CContinuousWorker::start(QThread::Priority priority)
|
||||||
@@ -184,7 +183,6 @@ namespace swift::misc
|
|||||||
|
|
||||||
moveToThread(thread);
|
moveToThread(thread);
|
||||||
connect(thread, &QThread::started, this, &CContinuousWorker::initialize);
|
connect(thread, &QThread::started, this, &CContinuousWorker::initialize);
|
||||||
connect(thread, &QThread::finished, &m_updateTimer, &QTimer::stop);
|
|
||||||
connect(thread, &QThread::finished, this, &CContinuousWorker::cleanup);
|
connect(thread, &QThread::finished, this, &CContinuousWorker::cleanup);
|
||||||
connect(thread, &QThread::finished, this, &CContinuousWorker::finish);
|
connect(thread, &QThread::finished, this, &CContinuousWorker::finish);
|
||||||
thread->start(priority);
|
thread->start(priority);
|
||||||
@@ -232,50 +230,6 @@ namespace swift::misc
|
|||||||
Q_UNUSED(ok)
|
Q_UNUSED(ok)
|
||||||
}
|
}
|
||||||
|
|
||||||
void CContinuousWorker::startUpdating(int updateTimeSecs)
|
|
||||||
{
|
|
||||||
Q_ASSERT_X(this->hasStarted(), Q_FUNC_INFO, "Worker not yet started");
|
|
||||||
if (!CThreadUtils::isInThisThread(this))
|
|
||||||
{
|
|
||||||
// shift in correct thread
|
|
||||||
QPointer<CContinuousWorker> myself(this);
|
|
||||||
QTimer::singleShot(0, this, [=] {
|
|
||||||
if (!myself) { return; }
|
|
||||||
this->doIfNotFinished([=] { startUpdating(updateTimeSecs); });
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// here in correct timer thread
|
|
||||||
if (updateTimeSecs < 0)
|
|
||||||
{
|
|
||||||
this->setEnabled(false);
|
|
||||||
m_updateTimer.stop();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
this->setEnabled(true);
|
|
||||||
m_updateTimer.start(1000 * updateTimeSecs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CContinuousWorker::stopUpdateTimer()
|
|
||||||
{
|
|
||||||
if (!m_updateTimer.isActive()) { return; }
|
|
||||||
|
|
||||||
// avoid "Timers cannot be stopped from another thread"
|
|
||||||
if (CThreadUtils::isInThisThread(&m_updateTimer)) { m_updateTimer.stop(); }
|
|
||||||
else
|
|
||||||
{
|
|
||||||
QPointer<CContinuousWorker> myself(this);
|
|
||||||
QTimer::singleShot(0, &m_updateTimer, [=] {
|
|
||||||
// stop timer in timer thread
|
|
||||||
if (!myself) { return; }
|
|
||||||
m_updateTimer.stop();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CContinuousWorker::finish()
|
void CContinuousWorker::finish()
|
||||||
{
|
{
|
||||||
this->setFinished();
|
this->setFinished();
|
||||||
|
|||||||
@@ -303,10 +303,6 @@ namespace swift::misc
|
|||||||
//! \threadsafe
|
//! \threadsafe
|
||||||
void setEnabled(bool enabled) { m_enabled = enabled; }
|
void setEnabled(bool enabled) { m_enabled = enabled; }
|
||||||
|
|
||||||
//! Start updating (start/stop timer)
|
|
||||||
//! \threadsafe
|
|
||||||
void startUpdating(int updateTimeSecs);
|
|
||||||
|
|
||||||
//! Name of the worker
|
//! Name of the worker
|
||||||
const QString &getName() { return m_name; }
|
const QString &getName() { return m_name; }
|
||||||
|
|
||||||
@@ -327,11 +323,6 @@ namespace swift::misc
|
|||||||
//! Wait time for quitAndWait, 0 means not waiting
|
//! Wait time for quitAndWait, 0 means not waiting
|
||||||
virtual unsigned long waitTimeoutMs() const { return 15 * 1000; }
|
virtual unsigned long waitTimeoutMs() const { return 15 * 1000; }
|
||||||
|
|
||||||
//! Safely stop update time
|
|
||||||
void stopUpdateTimer();
|
|
||||||
|
|
||||||
QTimer m_updateTimer { this }; //!< timer which can be used by implementing classes
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
//! Called after cleanup().
|
//! Called after cleanup().
|
||||||
void finish();
|
void finish();
|
||||||
|
|||||||
Reference in New Issue
Block a user