QGIS API Documentation  3.8.0-Zanzibar (11aff65)
qgstaskmanager.h
Go to the documentation of this file.
1 /***************************************************************************
2  qgstaskmanager.h
3  ----------------
4  begin : April 2016
5  copyright : (C) 2016 by Nyall Dawson
6  email : nyall dot dawson at gmail dot com
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
18 #ifndef QGSTASKMANAGER_H
19 #define QGSTASKMANAGER_H
20 
21 #include <QObject>
22 #include "qgis_sip.h"
23 #include <QMap>
24 #include <QFuture>
25 #include <QReadWriteLock>
26 
27 #include "qgis_core.h"
28 #include "qgsmaplayer.h"
29 
30 class QgsTask;
31 class QgsTaskRunnableWrapper;
32 
34 typedef QList< QgsTask * > QgsTaskList;
35 
52 class CORE_EXPORT QgsTask : public QObject
53 {
54  Q_OBJECT
55 
56  public:
57 
60  {
66  };
67 
69  enum Flag
70  {
71  CanCancel = 1 << 1,
72  AllFlags = CanCancel,
73  };
74  Q_DECLARE_FLAGS( Flags, Flag )
75 
76 
81  QgsTask( const QString &description = QString(), QgsTask::Flags flags = AllFlags );
82 
83  ~QgsTask() override;
84 
88  Flags flags() const { return mFlags; }
89 
93  bool canCancel() const { return mFlags & CanCancel; }
94 
99  bool isActive() const { return mOverallStatus == Running; }
100 
104  TaskStatus status() const { return mOverallStatus; }
105 
109  QString description() const { return mDescription; }
110 
114  double progress() const { return mTotalProgress; }
115 
123  qint64 elapsedTime() const;
124 
134  virtual void cancel();
135 
143  void hold();
144 
151  void unhold();
152 
155  {
156  SubTaskIndependent = 0,
158  };
159 
180  void addSubTask( QgsTask *subTask SIP_TRANSFER, const QgsTaskList &dependencies = QgsTaskList(),
181  SubTaskDependency subTaskDependency = SubTaskIndependent );
182 
188  void setDependentLayers( const QList<QgsMapLayer *> &dependentLayers );
189 
195  QList< QgsMapLayer * > dependentLayers() const;
196 
206  bool waitForFinished( int timeout = 30000 );
207 
208  signals:
209 
216  void progressChanged( double progress );
217 
224  void statusChanged( int status );
225 
231  void begun();
232 
238  void taskCompleted();
239 
247  void taskTerminated();
248 
249  protected:
250 
259  virtual bool run() = 0;
260 
271  virtual void finished( bool result ) { Q_UNUSED( result ) }
272 
278  bool isCanceled() const { return mShouldTerminate; }
279 
280  protected slots:
281 
287  void setProgress( double progress );
288 
289  private slots:
290  void subTaskStatusChanged( int status );
291 
292  private:
293 
294  Flags mFlags;
295  QString mDescription;
297  TaskStatus mStatus = Queued;
299  TaskStatus mOverallStatus = Queued;
300 
305  QMutex mNotFinishedMutex;
306 
308  double mProgress = 0.0;
310  double mTotalProgress = 0.0;
311  bool mShouldTerminate = false;
312  int mStartCount = 0;
313 
314  struct SubTask
315  {
316  SubTask( QgsTask *task, const QgsTaskList &dependencies, SubTaskDependency dependency )
317  : task( task )
318  , dependencies( dependencies )
319  , dependency( dependency )
320  {}
321  QgsTask *task = nullptr;
322  QgsTaskList dependencies;
323  SubTaskDependency dependency;
324  };
325  QList< SubTask > mSubTasks;
326 
327  QgsWeakMapLayerPointerList mDependentLayers;
328 
329  QElapsedTimer mElapsedTime;
330 
331 
335  void start();
336 
340  void completed();
341 
345  void terminated();
346 
347  void processSubTasksForCompletion();
348 
349  void processSubTasksForTermination();
350 
351  void processSubTasksForHold();
352 
353  friend class QgsTaskManager;
354  friend class QgsTaskRunnableWrapper;
355  friend class TestQgsTaskManager;
356 
357 };
358 
359 
360 Q_DECLARE_OPERATORS_FOR_FLAGS( QgsTask::Flags )
361 
362 
369 class CORE_EXPORT QgsTaskManager : public QObject
370 {
371  Q_OBJECT
372 
373  public:
374 
379  QgsTaskManager( QObject *parent SIP_TRANSFERTHIS = nullptr );
380 
381  ~QgsTaskManager() override;
382 
387  {
388 
393  explicit TaskDefinition( QgsTask *task, const QgsTaskList &dependentTasks = QgsTaskList() )
394  : task( task )
395  , dependentTasks( dependentTasks )
396  {}
397 
399  QgsTask *task = nullptr;
400 
407 
408  };
409 
418  long addTask( QgsTask *task SIP_TRANSFER, int priority = 0 );
419 
428  long addTask( const TaskDefinition &task SIP_TRANSFER, int priority = 0 );
429 
435  QgsTask *task( long id ) const;
436 
440  QList<QgsTask *> tasks() const;
441 
443  int count() const;
444 
450  long taskId( QgsTask *task ) const;
451 
457  void cancelAll();
458 
460  bool dependenciesSatisfied( long taskId ) const;
461 
466  QSet< long > dependencies( long taskId ) const SIP_SKIP;
467 
475  QList< QgsMapLayer * > dependentLayers( long taskId ) const;
476 
481  QList< QgsTask * > tasksDependentOnLayer( QgsMapLayer *layer ) const;
482 
487  QList< QgsTask * > activeTasks() const;
488 
494  int countActiveTasks() const;
495 
496  public slots:
497 
502  void triggerTask( QgsTask *task );
503 
504  signals:
505 
511  void progressChanged( long taskId, double progress );
512 
518  void finalTaskProgressChanged( double progress );
519 
525  void statusChanged( long taskId, int status );
526 
531  void taskAdded( long taskId );
532 
537  void taskAboutToBeDeleted( long taskId );
538 
543  void allTasksFinished();
544 
549  void countActiveTasksChanged( int count );
550 
557  void taskTriggered( QgsTask *task );
558 
559  private slots:
560 
561  void taskProgressChanged( double progress );
562  void taskStatusChanged( int status );
563  void layersWillBeRemoved( const QList<QgsMapLayer *> &layers );
564 
565  private:
566 
567  struct TaskInfo
568  {
569  TaskInfo( QgsTask *task = nullptr, int priority = 0 );
570  void createRunnable();
571  QgsTask *task = nullptr;
572  QAtomicInt added;
573  int priority;
574  QgsTaskRunnableWrapper *runnable = nullptr;
575  };
576 
577  mutable QMutex *mTaskMutex;
578 
579  QMap< long, TaskInfo > mTasks;
580  QMap< long, QgsTaskList > mTaskDependencies;
581  QMap< long, QgsWeakMapLayerPointerList > mLayerDependencies;
582 
584  long mNextTaskId = 1;
585 
587  QSet< QgsTask * > mActiveTasks;
589  QSet< QgsTask * > mParentTasks;
591  QSet< QgsTask * > mSubTasks;
592 
593  QSet< QgsTask * > mPendingDeletion;
594 
595  long addTaskPrivate( QgsTask *task,
596  QgsTaskList dependencies,
597  bool isSubTask,
598  int priority );
599 
600  bool cleanupAndDeleteTask( QgsTask *task );
601 
606  void processQueue();
607 
613  void cancelDependentTasks( long taskId );
614 
615  bool resolveDependencies( long firstTaskId, long currentTaskId, QSet< long > &results ) const;
616 
618  bool hasCircularDependencies( long taskId ) const;
619 
620  friend class TestQgsTaskManager;
621 };
622 
623 #endif //QGSTASKMANAGER_H
Base class for all map layer types.
Definition: qgsmaplayer.h:78
bool isActive() const
Returns true if the task is active, ie it is not complete and has not been canceled.
#define SIP_TRANSFERTHIS
Definition: qgis_sip.h:46
QList< QgsTask *> QgsTaskList
List of QgsTask objects.
Subtask must complete before parent can begin.
TaskStatus
Status of tasks.
bool isCanceled() const
Will return true if task should terminate ASAP.
SubTaskDependency
Controls how subtasks relate to their parent task.
QgsTaskList dependentTasks
List of dependent tasks which must be completed before task can run.
Task was terminated or errored.
QString description() const
Returns the task&#39;s description.
Definition of a task for inclusion in the manager.
#define SIP_SKIP
Definition: qgis_sip.h:119
Task is queued but on hold and will not be started.
Abstract base class for long running background tasks.
#define SIP_TRANSFER
Definition: qgis_sip.h:36
bool canCancel() const
Returns true if the task can be canceled.
Task successfully completed.
Task manager for managing a set of long-running QgsTask tasks.
Task is queued and has not begun.
TaskDefinition(QgsTask *task, const QgsTaskList &dependentTasks=QgsTaskList())
Constructor for TaskDefinition.
double progress() const
Returns the task&#39;s progress (between 0.0 and 100.0)
Task is currently running.
QList< QgsWeakMapLayerPointer > QgsWeakMapLayerPointerList
A list of weak pointers to QgsMapLayers.
Definition: qgsmaplayer.h:1583
virtual void finished(bool result)
If the task is managed by a QgsTaskManager, this will be called after the task has finished (whether ...
Flag
Task flags.
TaskStatus status() const
Returns the current task status.
Flags flags() const
Returns the flags associated with the task.