T66 A new smart pointer for managing a CContinuousWorker subclass instance.

Owns the worker before it starts, when ownership is transferred to the thread.
This commit is contained in:
Mathew Sutcliffe
2017-05-06 23:46:53 +01:00
parent ca81c65eae
commit 41ff563e19
4 changed files with 70 additions and 8 deletions

View File

@@ -56,6 +56,7 @@ namespace BlackMisc
CWorker *CWorker::fromTaskImpl(QObject *owner, const QString &name, int typeId, std::function<CVariant()> task)
{
auto *worker = new CWorker(task);
emit worker->aboutToStart();
worker->setStarted();
auto *thread = new CRegularThread(owner);
@@ -122,6 +123,7 @@ namespace BlackMisc
if (m_name.isEmpty()) { m_name = metaObject()->className(); }
emit aboutToStart();
setStarted();
auto *thread = new CRegularThread(m_owner);

View File

@@ -23,6 +23,7 @@
#include <QMutex>
#include <QMutexLocker>
#include <QObject>
#include <QPointer>
#include <QSharedPointer>
#include <QString>
#include <QThread>
@@ -31,12 +32,16 @@
#include <QtGlobal>
#include <algorithm>
#include <functional>
#include <memory>
#include <type_traits>
#include <atomic>
namespace BlackMisc
{
template <typename T>
class CWorkerPointer;
/*!
* Starts a single-shot timer which will call a task in the thread of the given object when it times out.
*
@@ -158,6 +163,9 @@ namespace BlackMisc
void abandonAndWait() noexcept;
signals:
//! Emitted when the task is about to start.
void aboutToStart();
//! Emitted when the task is finished.
void finished();
@@ -292,6 +300,9 @@ namespace BlackMisc
void ps_finish();
private:
template <typename T>
friend class CWorkerPointer;
using CWorkerBase::hasStarted;
using CWorkerBase::setStarted;
using CWorkerBase::setFinished;
@@ -300,6 +311,59 @@ namespace BlackMisc
QString m_name;
};
/*!
* RAII smart pointer to manage a CContinuousWorker instance.
*
* Not required if the worker is immediately started after construction.
* Before the worker starts, it is owned by the pointer.
* After the worker starts, becomes a non-owning pointer, as ownership is tied to the lifetime of the thread.
*/
template <typename T>
class CWorkerPointer
{
public:
static_assert(std::is_base_of<CContinuousWorker, T>::value, "T must be a CContinuousWorker subclass");
//! Constructor. Takes ownership.
explicit CWorkerPointer(T *ptr) : m_weak(ptr)
{
if (!ptr || static_cast<const CContinuousWorker *>(ptr)->hasStarted()) { return; }
m_strong.reset(ptr);
QObject::connect(ptr, &CWorkerBase::aboutToStart, [this] { m_strong.reset(); });
}
//! Construct a null pointer.
//! @{
CWorkerPointer() = default;
CWorkerPointer(std::nullptr_t) {}
//! @}
//! Factory method.
//! Arguments are forwarded to the constructor of T. Strictly more exception-safe than calling the constructor with new.
template <typename... Ts>
static CWorkerPointer create(Ts &&... args) { return CWorkerPointer(new T(std::forward<Ts>(args)...)); }
//! Access the raw pointer.
//! @{
T *data() const { return m_weak.data(); }
T &operator *() const { return *data(); }
T *operator ->() const { return &*data(); }
//! @}
//! True if it points to a valid worker.
//! @{
explicit operator bool() const { return m_weak; }
bool isValid() const { return m_weak; }
//! @}
//! True if it owns the worker it points to (i.e. worker has not yet started).
bool isOwner() const { return m_strong; }
private:
std::unique_ptr<T> m_strong;
QPointer<T> m_weak;
};
}
#endif

View File

@@ -8,7 +8,6 @@
*/
#include "swiftdata.h"
#include "blackcore/db/backgrounddataupdater.h"
#include "blackcore/data/globalsetup.h"
#include "blackgui/components/datamaininfoareacomponent.h"
#include "blackgui/components/dbmappingcomponent.h"
@@ -163,14 +162,14 @@ void CSwiftData::consolidationSettingChanged()
{
ui->comp_MainInfoArea->getDataSettingsComponent()->setBackgroundUpdater(nullptr);
m_updater->gracefulShutdown();
m_updater.reset(nullptr);
m_updater = nullptr;
}
}
else
{
if (!m_updater)
{
m_updater.reset(new CBackgroundDataUpdater(this));
m_updater = m_updater.create(this);
m_updater->start(QThread::LowestPriority);
ui->comp_MainInfoArea->getDataSettingsComponent()->setBackgroundUpdater(m_updater.data());
}

View File

@@ -15,6 +15,7 @@
#include "blackgui/settings/guisettings.h"
#include "blackgui/mainwindowaccess.h"
#include "blackgui/managedstatusbar.h"
#include "blackcore/db/backgrounddataupdater.h"
#include "blackmisc/identifiable.h"
#include "blackmisc/statusmessage.h"
@@ -28,10 +29,6 @@ namespace Ui { class CSwiftData; }
namespace BlackCore
{
class CWebDataServices;
namespace Db
{
class CBackgroundDataUpdater;
}
}
/*!
@@ -83,7 +80,7 @@ private:
BlackGui::CManagedStatusBar m_statusBar;
QScopedPointer<Ui::CSwiftData> ui;
QScopedPointer<BlackCore::Db::CBackgroundDataUpdater, QScopedPointerDeleteLater> m_updater;
BlackMisc::CWorkerPointer<BlackCore::Db::CBackgroundDataUpdater> m_updater;
BlackMisc::CSettingReadOnly<BlackGui::Settings::TBackgroundConsolidation> m_consolidationSettings { this, &CSwiftData::consolidationSettingChanged }; //!< consolidation time
};