QGIS API Documentation  3.14.0-Pi (9f7028fd23)
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  Q_ENUM( TaskStatus )
68 
69 
70  enum Flag
71  {
72  CanCancel = 1 << 1,
73  CancelWithoutPrompt = 1 << 2,
74  AllFlags = CanCancel,
75  };
76  Q_DECLARE_FLAGS( Flags, Flag )
77 
78 
83  QgsTask( const QString &description = QString(), QgsTask::Flags flags = AllFlags );
84 
85  ~QgsTask() override;
86 
90  Flags flags() const { return mFlags; }
91 
97  void setDescription( const QString &description );
98 
102  bool canCancel() const { return mFlags & CanCancel; }
103 
108  bool isActive() const { return mOverallStatus == Running; }
109 
113  TaskStatus status() const { return mOverallStatus; }
114 
118  QString description() const { return mDescription; }
119 
123  double progress() const { return mTotalProgress; }
124 
132  qint64 elapsedTime() const;
133 
143  virtual void cancel();
144 
152  void hold();
153 
160  void unhold();
161 
164  {
165  SubTaskIndependent = 0,
167  };
168 
189  void addSubTask( QgsTask *subTask SIP_TRANSFER, const QgsTaskList &dependencies = QgsTaskList(),
190  SubTaskDependency subTaskDependency = SubTaskIndependent );
191 
197  void setDependentLayers( const QList<QgsMapLayer *> &dependentLayers );
198 
204  QList< QgsMapLayer * > dependentLayers() const;
205 
215  bool waitForFinished( int timeout = 30000 );
216 
217  signals:
218 
225  void progressChanged( double progress );
226 
233  void statusChanged( int status );
234 
240  void begun();
241 
247  void taskCompleted();
248 
256  void taskTerminated();
257 
258  protected:
259 
268  virtual bool run() = 0;
269 
280  virtual void finished( bool result ) { Q_UNUSED( result ) }
281 
287  bool isCanceled() const;
288 
289  protected slots:
290 
296  void setProgress( double progress );
297 
298  private slots:
299  void subTaskStatusChanged( int status );
300 
301  private:
302 
303  Flags mFlags;
304  QString mDescription;
306  TaskStatus mStatus = Queued;
308  TaskStatus mOverallStatus = Queued;
309 
314  QMutex mNotFinishedMutex;
315 
320  QSemaphore mNotStartedMutex;
321 
323  double mProgress = 0.0;
325  double mTotalProgress = 0.0;
326  bool mShouldTerminate = false;
327  mutable QMutex mShouldTerminateMutex;
328  int mStartCount = 0;
329 
330  struct SubTask
331  {
332  SubTask( QgsTask *task, const QgsTaskList &dependencies, SubTaskDependency dependency )
333  : task( task )
334  , dependencies( dependencies )
335  , dependency( dependency )
336  {}
337  QgsTask *task = nullptr;
338  QgsTaskList dependencies;
339  SubTaskDependency dependency;
340  };
341  QList< SubTask > mSubTasks;
342 
343  QgsWeakMapLayerPointerList mDependentLayers;
344 
345  QElapsedTimer mElapsedTime;
346 
347 
351  void start();
352 
356  void completed();
357 
361  void terminated();
362 
363 
364  void processSubTasksForHold();
365 
366  friend class QgsTaskManager;
367  friend class QgsTaskRunnableWrapper;
368  friend class TestQgsTaskManager;
369 
370  private slots:
371 
372  void processSubTasksForCompletion();
373 
374  void processSubTasksForTermination();
375 
376 };
377 
378 
379 Q_DECLARE_OPERATORS_FOR_FLAGS( QgsTask::Flags )
380 
381 
388 class CORE_EXPORT QgsTaskManager : public QObject
389 {
390  Q_OBJECT
391 
392  public:
393 
398  QgsTaskManager( QObject *parent SIP_TRANSFERTHIS = nullptr );
399 
400  ~QgsTaskManager() override;
401 
406  {
407 
412  explicit TaskDefinition( QgsTask *task, const QgsTaskList &dependentTasks = QgsTaskList() )
413  : task( task )
414  , dependentTasks( dependentTasks )
415  {}
416 
418  QgsTask *task = nullptr;
419 
426 
427  };
428 
437  long addTask( QgsTask *task SIP_TRANSFER, int priority = 0 );
438 
447  long addTask( const TaskDefinition &task SIP_TRANSFER, int priority = 0 );
448 
454  QgsTask *task( long id ) const;
455 
459  QList<QgsTask *> tasks() const;
460 
462  int count() const;
463 
469  long taskId( QgsTask *task ) const;
470 
476  void cancelAll();
477 
479  bool dependenciesSatisfied( long taskId ) const;
480 
485  QSet< long > dependencies( long taskId ) const SIP_SKIP;
486 
494  QList< QgsMapLayer * > dependentLayers( long taskId ) const;
495 
500  QList< QgsTask * > tasksDependentOnLayer( QgsMapLayer *layer ) const;
501 
506  QList< QgsTask * > activeTasks() const;
507 
513  int countActiveTasks() const;
514 
515  public slots:
516 
521  void triggerTask( QgsTask *task );
522 
523  signals:
524 
530  void progressChanged( long taskId, double progress );
531 
537  void finalTaskProgressChanged( double progress );
538 
544  void statusChanged( long taskId, int status );
545 
550  void taskAdded( long taskId );
551 
556  void taskAboutToBeDeleted( long taskId );
557 
562  void allTasksFinished();
563 
568  void countActiveTasksChanged( int count );
569 
576  void taskTriggered( QgsTask *task );
577 
578  private slots:
579 
580  void taskProgressChanged( double progress );
581  void taskStatusChanged( int status );
582  void layersWillBeRemoved( const QList<QgsMapLayer *> &layers );
583 
584  private:
585 
586  struct TaskInfo
587  {
588  TaskInfo( QgsTask *task = nullptr, int priority = 0 );
589  void createRunnable();
590  QgsTask *task = nullptr;
591  QAtomicInt added;
592  int priority;
593  QgsTaskRunnableWrapper *runnable = nullptr;
594  };
595 
596  bool mInitialized = false;
597 
598  mutable QMutex *mTaskMutex;
599 
600  QMap< long, TaskInfo > mTasks;
601  QMap< long, QgsTaskList > mTaskDependencies;
602  QMap< long, QgsWeakMapLayerPointerList > mLayerDependencies;
603 
605  long mNextTaskId = 1;
606 
608  QSet< QgsTask * > mActiveTasks;
610  QSet< QgsTask * > mParentTasks;
612  QSet< QgsTask * > mSubTasks;
613 
614  QSet< QgsTask * > mPendingDeletion;
615 
616  long addTaskPrivate( QgsTask *task,
617  QgsTaskList dependencies,
618  bool isSubTask,
619  int priority );
620 
621  bool cleanupAndDeleteTask( QgsTask *task );
622 
627  void processQueue();
628 
634  void cancelDependentTasks( long taskId );
635 
636  bool resolveDependencies( long firstTaskId, long currentTaskId, QSet< long > &results ) const;
637 
639  bool hasCircularDependencies( long taskId ) const;
640 
641  friend class TestQgsTaskManager;
642 };
643 
644 #endif //QGSTASKMANAGER_H
QgsWeakMapLayerPointerList
QList< QgsWeakMapLayerPointer > QgsWeakMapLayerPointerList
A list of weak pointers to QgsMapLayers.
Definition: qgsmaplayer.h:1677
QgsTaskManager::TaskDefinition::dependentTasks
QgsTaskList dependentTasks
List of dependent tasks which must be completed before task can run.
Definition: qgstaskmanager.h:425
QgsTask::SubTaskDependency
SubTaskDependency
Controls how subtasks relate to their parent task.
Definition: qgstaskmanager.h:163
QgsTask::Complete
@ Complete
Task successfully completed.
Definition: qgstaskmanager.h:64
QgsTask::description
QString description() const
Returns the task's description.
Definition: qgstaskmanager.h:118
QgsTask::Running
@ Running
Task is currently running.
Definition: qgstaskmanager.h:63
QgsTask::finished
virtual void finished(bool result)
If the task is managed by a QgsTaskManager, this will be called after the task has finished (whether ...
Definition: qgstaskmanager.h:280
QgsTask::Queued
@ Queued
Task is queued and has not begun.
Definition: qgstaskmanager.h:61
QgsTaskManager::TaskDefinition
Definition of a task for inclusion in the manager.
Definition: qgstaskmanager.h:405
QgsTaskManager::TaskDefinition::TaskDefinition
TaskDefinition(QgsTask *task, const QgsTaskList &dependentTasks=QgsTaskList())
Constructor for TaskDefinition.
Definition: qgstaskmanager.h:412
QgsTask::status
TaskStatus status() const
Returns the current task status.
Definition: qgstaskmanager.h:113
SIP_SKIP
#define SIP_SKIP
Definition: qgis_sip.h:126
QgsTask::canCancel
bool canCancel() const
Returns true if the task can be canceled.
Definition: qgstaskmanager.h:102
QgsTask::TaskStatus
TaskStatus
Status of tasks.
Definition: qgstaskmanager.h:59
qgsmaplayer.h
QgsTaskManager
Task manager for managing a set of long-running QgsTask tasks. This class can be created directly,...
Definition: qgstaskmanager.h:388
qgis_sip.h
SIP_TRANSFER
#define SIP_TRANSFER
Definition: qgis_sip.h:36
QgsTask::ParentDependsOnSubTask
@ ParentDependsOnSubTask
Subtask must complete before parent can begin.
Definition: qgstaskmanager.h:166
QgsTask::isActive
bool isActive() const
Returns true if the task is active, ie it is not complete and has not been canceled.
Definition: qgstaskmanager.h:108
QgsTaskList
QList< QgsTask * > QgsTaskList
List of QgsTask objects.
Definition: qgstaskmanager.h:31
QgsTask::Terminated
@ Terminated
Task was terminated or errored.
Definition: qgstaskmanager.h:65
QgsMapLayer
Definition: qgsmaplayer.h:81
QgsTask::flags
Flags flags() const
Returns the flags associated with the task.
Definition: qgstaskmanager.h:90
QgsTask::OnHold
@ OnHold
Task is queued but on hold and will not be started.
Definition: qgstaskmanager.h:62
SIP_TRANSFERTHIS
#define SIP_TRANSFERTHIS
Definition: qgis_sip.h:53
QgsTask::Flag
Flag
Task flags.
Definition: qgstaskmanager.h:70
QgsTask::progress
double progress() const
Returns the task's progress (between 0.0 and 100.0)
Definition: qgstaskmanager.h:123
QgsTask
Abstract base class for long running background tasks. Tasks can be controlled directly,...
Definition: qgstaskmanager.h:52