mirror of
https://github.com/swift-project/pilotclient.git
synced 2026-04-03 07:35:48 +08:00
refs #380, use CWorker instead of QConcurrent for threaded reader (bookings/VATSIM file)
This commit is contained in:
83
src/blackmisc/threadedreader.cpp
Normal file
83
src/blackmisc/threadedreader.cpp
Normal file
@@ -0,0 +1,83 @@
|
||||
/* Copyright (C) 2013
|
||||
* swift project Community / Contributors
|
||||
*
|
||||
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
|
||||
* directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project,
|
||||
* including this file, may be copied, modified, propagated, or distributed except according to the terms
|
||||
* contained in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "threadedreader.h"
|
||||
|
||||
namespace BlackMisc
|
||||
{
|
||||
|
||||
CThreadedReader::CThreadedReader(QObject *owner, const QString &name) :
|
||||
CContinuousWorker(owner, name),
|
||||
m_updateTimer(new QTimer(this))
|
||||
{ }
|
||||
|
||||
|
||||
QDateTime CThreadedReader::getUpdateTimestamp() const
|
||||
{
|
||||
QReadLocker(&this->m_lock);
|
||||
return this->m_updateTimestamp;
|
||||
}
|
||||
|
||||
void CThreadedReader::setUpdateTimestamp(const QDateTime &updateTimestamp)
|
||||
{
|
||||
QWriteLocker(&this->m_lock);
|
||||
this->m_updateTimestamp = updateTimestamp;
|
||||
}
|
||||
|
||||
void CThreadedReader::requestStop()
|
||||
{
|
||||
QWriteLocker(&this->m_lock);
|
||||
this->m_stopped = true;
|
||||
this->m_updateTimer->stop();
|
||||
}
|
||||
|
||||
CThreadedReader::~CThreadedReader()
|
||||
{
|
||||
cleanup();
|
||||
}
|
||||
|
||||
void CThreadedReader::cleanup()
|
||||
{
|
||||
// cleanup code would go here
|
||||
}
|
||||
|
||||
bool CThreadedReader::isFinished() const
|
||||
{
|
||||
if (CContinuousWorker::isFinished()) { return true; }
|
||||
QReadLocker(&this->m_lock);
|
||||
return this->m_stopped;
|
||||
}
|
||||
|
||||
void CThreadedReader::setInterval(int updatePeriodMs)
|
||||
{
|
||||
Q_ASSERT(this->m_updateTimer);
|
||||
QWriteLocker(&this->m_lock);
|
||||
if (updatePeriodMs < 1)
|
||||
{
|
||||
this->m_updateTimer->stop();
|
||||
}
|
||||
else
|
||||
{
|
||||
this->m_updateTimer->start(updatePeriodMs);
|
||||
}
|
||||
}
|
||||
|
||||
int CThreadedReader::interval() const
|
||||
{
|
||||
QReadLocker rl(&this->m_lock);
|
||||
return this->m_updateTimer->interval();
|
||||
}
|
||||
|
||||
void CThreadedReader::threadAssertCheck() const
|
||||
{
|
||||
Q_ASSERT_X(QCoreApplication::instance()->thread() != QThread::currentThread(), "CThreadedReader::threadAssertCheck", "Needs to run in own thread");
|
||||
Q_ASSERT_X(QObject::thread() == QThread::currentThread(), "CThreadedReader::threadAssertCheck", "Needs to run in own thread");
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@@ -17,7 +17,6 @@
|
||||
#include <QDateTime>
|
||||
#include <QTimer>
|
||||
#include <QNetworkReply>
|
||||
#include <QFuture>
|
||||
#include <QCoreApplication>
|
||||
|
||||
namespace BlackMisc
|
||||
@@ -25,102 +24,55 @@ namespace BlackMisc
|
||||
/*!
|
||||
* Support for threaded based reading and parsing tasks such
|
||||
* as data files via http, or file system and parsing (such as FSX models)
|
||||
*
|
||||
* \remarks Header only class to avoid forward instantiations across subprojects
|
||||
*/
|
||||
template <class FutureRet = void> class CThreadedReader : public CContinuousWorker
|
||||
class CThreadedReader : public CContinuousWorker
|
||||
{
|
||||
public:
|
||||
//! Thread safe, set update timestamp
|
||||
//! \threadsafe
|
||||
QDateTime getUpdateTimestamp() const
|
||||
{
|
||||
QReadLocker(&this->m_lock);
|
||||
return this->m_updateTimestamp;
|
||||
}
|
||||
QDateTime getUpdateTimestamp() const;
|
||||
|
||||
//! Thread safe, set update timestamp
|
||||
//! \threadsafe
|
||||
void setUpdateTimestamp(const QDateTime &updateTimestamp)
|
||||
{
|
||||
QWriteLocker(&this->m_lock);
|
||||
this->m_updateTimestamp = updateTimestamp;
|
||||
}
|
||||
void setUpdateTimestamp(const QDateTime &updateTimestamp);
|
||||
|
||||
//! Request to stop
|
||||
//! \threadsafe
|
||||
void requestStop();
|
||||
|
||||
//! Destructor
|
||||
virtual ~CThreadedReader();
|
||||
|
||||
//! \copydoc CContinuousWorker::cleanup
|
||||
virtual void cleanup() override
|
||||
{
|
||||
// shutdown pending
|
||||
QWriteLocker(&this->m_lock);
|
||||
if (this->m_pendingFuture.isRunning())
|
||||
{
|
||||
// cancel does not work with all futures, especially not with QConcurrent::run
|
||||
// the stop flag should the job
|
||||
// but I will cancel anyway
|
||||
this->m_pendingFuture.cancel();
|
||||
}
|
||||
if (this->m_pendingNetworkReply && this->m_pendingNetworkReply->isRunning())
|
||||
{
|
||||
this->m_pendingNetworkReply->abort();
|
||||
}
|
||||
virtual void cleanup() override;
|
||||
|
||||
// cancel or stop flag above should terminate QFuture
|
||||
this->m_pendingFuture.waitForFinished();
|
||||
}
|
||||
//! Thread ended of stop requested
|
||||
virtual bool isFinished() const override;
|
||||
|
||||
/*!
|
||||
* Set the update time
|
||||
* \param updatePeriodMs <=0 stops the timer
|
||||
* \threadsafe
|
||||
*/
|
||||
void setInterval(int updatePeriodMs)
|
||||
{
|
||||
Q_ASSERT(this->m_updateTimer);
|
||||
QWriteLocker(&this->m_lock);
|
||||
if (updatePeriodMs < 1)
|
||||
this->m_updateTimer->stop();
|
||||
else
|
||||
this->m_updateTimer->start(updatePeriodMs);
|
||||
}
|
||||
void setInterval(int updatePeriodMs);
|
||||
|
||||
//! Get the timer interval (ms)
|
||||
//! \threadsafe
|
||||
int interval() const
|
||||
{
|
||||
QReadLocker rl(&this->m_lock);
|
||||
return this->m_updateTimer->interval();
|
||||
}
|
||||
int interval() const;
|
||||
|
||||
protected:
|
||||
//! Constructor
|
||||
CThreadedReader(QObject *owner) : CContinuousWorker(owner),
|
||||
m_updateTimer(new QTimer(this)), m_lock(QReadWriteLock::Recursive)
|
||||
{
|
||||
}
|
||||
CThreadedReader(QObject *owner, const QString &name);
|
||||
|
||||
//! Has pending network replay
|
||||
//! \threadsafe
|
||||
void setPendingNetworkReply(QNetworkReply *reply)
|
||||
{
|
||||
QWriteLocker(&this->m_lock);
|
||||
this->m_pendingNetworkReply = reply;
|
||||
}
|
||||
QTimer *m_updateTimer = nullptr; //!< update timer
|
||||
mutable QReadWriteLock m_lock {QReadWriteLock::Recursive}; //!< lock
|
||||
|
||||
//! Has pending operation
|
||||
//! \threadsafe
|
||||
void setPendingFuture(QFuture<FutureRet> future)
|
||||
{
|
||||
QWriteLocker(&this->m_lock);
|
||||
this->m_pendingFuture = future;
|
||||
}
|
||||
|
||||
QTimer *m_updateTimer = nullptr; //!< update timer
|
||||
mutable QReadWriteLock m_lock; //!< lock
|
||||
//! Make sure everthing runs correctly in own thread
|
||||
void threadAssertCheck() const;
|
||||
|
||||
private:
|
||||
QDateTime m_updateTimestamp; //!< when was file / resource read
|
||||
QFuture<FutureRet> m_pendingFuture; //!< optional future to be stopped
|
||||
QNetworkReply *m_pendingNetworkReply = nullptr; //!< optional network reply to be stopped
|
||||
QDateTime m_updateTimestamp; //!< when was file / resource read
|
||||
bool m_stopped = false; //!< optional network reply to be stopped
|
||||
};
|
||||
} // namespace
|
||||
|
||||
|
||||
@@ -130,7 +130,7 @@ namespace BlackMisc
|
||||
|
||||
//! Returns true if the task has finished.
|
||||
//! \threadsafe But don't rely on this condition remaining true for any length of time.
|
||||
bool isFinished() const
|
||||
virtual bool isFinished() const
|
||||
{
|
||||
QMutexLocker lock(&m_finishedMutex);
|
||||
return m_finished;
|
||||
|
||||
Reference in New Issue
Block a user