From f8af6334fb70a117595afed74c48cf9ca314e302 Mon Sep 17 00:00:00 2001 From: Mark Liversedge Date: Sun, 1 Apr 2018 14:46:30 +0100 Subject: [PATCH] Estimator lazy refresh .. Refresh model estimates when rides added, deleted, saved. .. Lazy refresh will cancel any pending or running threads and trigger a new one in 15 secs time. .. This strategy allows us to call a lazy refresh even when importing large number of rides, since the start will be delayed and cancelled by the next ride added etc. .. The thread stop() function is also called by the destructor to stop when the user exits and avoiding delay/SEGV on exit. --- src/Core/RideCache.cpp | 6 +++++ src/Core/RideCache.h | 1 + src/Gui/SaveDialogs.cpp | 4 ++++ src/Metrics/Estimator.cpp | 48 +++++++++++++++++++++++++++++++++++++++ src/Metrics/Estimator.h | 17 +++++++++++--- 5 files changed, 73 insertions(+), 3 deletions(-) diff --git a/src/Core/RideCache.cpp b/src/Core/RideCache.cpp index 410ef2e46..9daf31457 100644 --- a/src/Core/RideCache.cpp +++ b/src/Core/RideCache.cpp @@ -287,6 +287,9 @@ RideCache::addRide(QString name, bool dosignal, bool select, bool useTempActivit // notify everyone to select the one we were already on context->notifyRideSelected(prior); } + + // model estimates (lazy refresh) + estimator->refresh(); } void @@ -376,6 +379,9 @@ RideCache::removeCurrentRide() // now select another ride context->notifyRideSelected(select); + + // model estimates (lazy refresh) + estimator->refresh(); } // NOTE: diff --git a/src/Core/RideCache.h b/src/Core/RideCache.h index 92ab90633..f129088fd 100644 --- a/src/Core/RideCache.h +++ b/src/Core/RideCache.h @@ -132,6 +132,7 @@ class RideCache : public QObject protected: friend class ::Athlete; + friend class ::MainWindow; // save dialog friend class ::RideCacheBackgroundRefresh; Context *context; diff --git a/src/Gui/SaveDialogs.cpp b/src/Gui/SaveDialogs.cpp index 0042d79ae..3a31e4424 100644 --- a/src/Gui/SaveDialogs.cpp +++ b/src/Gui/SaveDialogs.cpp @@ -19,6 +19,7 @@ #include "Tab.h" #include "Athlete.h" #include "RideCache.h" +#include "Estimator.h" #include "GcRideFile.h" #include "JsonRideFile.h" #include "RideItem.h" @@ -197,6 +198,9 @@ MainWindow::saveSilent(Context *context, RideItem *rideItem) // mark clean as we have now saved the data rideItem->ride()->emitSaved(); + + // model estimates (lazy refresh) + context->athlete->rideCache->estimator->refresh(); } diff --git a/src/Metrics/Estimator.cpp b/src/Metrics/Estimator.cpp index 7ee7cf5fd..9ae2453ec 100644 --- a/src/Metrics/Estimator.cpp +++ b/src/Metrics/Estimator.cpp @@ -99,10 +99,51 @@ class RollingBests { Estimator::Estimator(Context *context) : context(context) { + // used to flag when we need to stop + abort = false; + + // lazy start signal + connect(&singleshot, SIGNAL(timeout()), this, SLOT(calculate())); + // when thread finishes we can let everyone know estimates are updated connect(this, SIGNAL(finished()), context, SLOT(notifyEstimatesRefreshed())); } +void +Estimator::stop() +{ + if (isRunning()) { + + // we could use requestInterruption but would mean we need QT > 5.2 + // and there isn't much value in that. + abort = true; + + // now wait for the thread to stop + while(isRunning() && abort == true) msleep(50); + } +} + +// terminate thread before closing +Estimator::~Estimator() +{ + stop(); +} + +// refresh +void +Estimator::refresh() +{ + printd("Lazy start triggered.\n"); + + stop(); // stop any running threads + singleshot.stop(); // stop any pending threads + + // 15 secs delay before calculate() is triggered + singleshot.setSingleShot(true); + singleshot.setInterval(15000); + singleshot.start(); +} + // setup and run, if not already running void Estimator::calculate() @@ -184,6 +225,13 @@ Estimator::run() QDate date = from; while (date < to) { + // check if we've been asked to stop + if (abort == true) { + printd("Model estimator aborted.\n"); + abort = false; + return; + } + QDate begin = date; QDate end = date.addDays(6); diff --git a/src/Metrics/Estimator.h b/src/Metrics/Estimator.h index 594fe2887..416c1fd2d 100644 --- a/src/Metrics/Estimator.h +++ b/src/Metrics/Estimator.h @@ -38,13 +38,22 @@ class Estimator : public QThread { public: Estimator(Context *); - - // sets up and kicks off thread - void calculate(); + ~Estimator(); // perform calculation in thread void run(); + // halt the thread + void stop(); + + // cancel any pending/running and kick off with 15 sec delay + void refresh(); + + public slots: + + // setup and run estimators + void calculate(); + protected: friend class ::Athlete; @@ -53,7 +62,9 @@ class Estimator : public QThread { QMutex lock; QList estimates; QVector rides; // worklist + QTimer singleshot; + bool abort; }; #endif