QGIS API Documentation  3.2.0-Bonn (bc43194)
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 "qgis.h"
24 #include <QMap>
25 #include <QFuture>
26 #include <QReadWriteLock>
27 
28 #include "qgis_core.h"
29 #include "qgsmaplayer.h"
30 
31 class QgsTask;
32 class QgsTaskRunnableWrapper;
33 
35 typedef QList< QgsTask * > QgsTaskList;
36 
53 class CORE_EXPORT QgsTask : public QObject
54 {
55  Q_OBJECT
56 
57  public:
58 
61  {
67  };
68 
70  enum Flag
71  {
72  CanCancel = 1 << 1,
73  AllFlags = CanCancel,
74  };
75  Q_DECLARE_FLAGS( Flags, Flag )
76 
77 
82  QgsTask( const QString &description = QString(), QgsTask::Flags flags = AllFlags );
83 
84  ~QgsTask() override;
85 
89  Flags flags() const { return mFlags; }
90 
94  bool canCancel() const { return mFlags & CanCancel; }
95 
100  bool isActive() const { return mOverallStatus == Running; }
101 
105  TaskStatus status() const { return mOverallStatus; }
106 
110  QString description() const { return mDescription; }
111 
115  double progress() const { return mTotalProgress; }
116 
126  virtual void cancel();
127 
135  void hold();
136 
143  void unhold();
144 
147  {
148  SubTaskIndependent = 0,
150  };
151 
172  void addSubTask( QgsTask *subTask SIP_TRANSFER, const QgsTaskList &dependencies = QgsTaskList(),
173  SubTaskDependency subTaskDependency = SubTaskIndependent );
174 
180  void setDependentLayers( const QList<QgsMapLayer *> &dependentLayers );
181 
187  QList< QgsMapLayer * > dependentLayers() const;
188 
198  bool waitForFinished( unsigned long timeout = 30000 );
199 
200  signals:
201 
208  void progressChanged( double progress );
209 
216  void statusChanged( int status );
217 
223  void begun();
224 
230  void taskCompleted();
231 
239  void taskTerminated();
240 
241  protected:
242 
251  virtual bool run() = 0;
252 
263  virtual void finished( bool result ) { Q_UNUSED( result ); }
264 
270  bool isCanceled() const { return mShouldTerminate; }
271 
272  protected slots:
273 
279  void setProgress( double progress );
280 
281  private slots:
282  void subTaskStatusChanged( int status );
283 
284  private:
285 
286  Flags mFlags;
287  QString mDescription;
289  TaskStatus mStatus = Queued;
291  TaskStatus mOverallStatus = Queued;
292 
297  QMutex mNotFinishedMutex;
298 
300  double mProgress = 0.0;
302  double mTotalProgress = 0.0;
303  bool mShouldTerminate = false;
304  int mStartCount = 0;
305 
306  QWaitCondition mTaskFinished;
307 
308  struct SubTask
309  {
310  SubTask( QgsTask *task, const QgsTaskList &dependencies, SubTaskDependency dependency )
311  : task( task )
312  , dependencies( dependencies )
313  , dependency( dependency )
314  {}
315  QgsTask *task = nullptr;
316  QgsTaskList dependencies;
317  SubTaskDependency dependency;
318  };
319  QList< SubTask > mSubTasks;
320 
321  QgsWeakMapLayerPointerList mDependentLayers;
322 
323 
327  void start();
328 
332  void completed();
333 
337  void terminated();
338 
339  void processSubTasksForCompletion();
340 
341  void processSubTasksForTermination();
342 
343  void processSubTasksForHold();
344 
345  friend class QgsTaskManager;
346  friend class QgsTaskRunnableWrapper;
347  friend class TestQgsTaskManager;
348 
349 };
350 
351 
352 Q_DECLARE_OPERATORS_FOR_FLAGS( QgsTask::Flags )
353 
354 
361 class CORE_EXPORT QgsTaskManager : public QObject
362 {
363  Q_OBJECT
364 
365  public:
366 
371  QgsTaskManager( QObject *parent SIP_TRANSFERTHIS = nullptr );
372 
373  ~QgsTaskManager() override;
374 
379  {
380 
385  explicit TaskDefinition( QgsTask *task, const QgsTaskList &dependentTasks = QgsTaskList() )
386  : task( task )
387  , dependentTasks( dependentTasks )
388  {}
389 
391  QgsTask *task = nullptr;
392 
399 
400  };
401 
410  long addTask( QgsTask *task SIP_TRANSFER, int priority = 0 );
411 
420  long addTask( const TaskDefinition &task SIP_TRANSFER, int priority = 0 );
421 
427  QgsTask *task( long id ) const;
428 
432  QList<QgsTask *> tasks() const;
433 
435  int count() const;
436 
442  long taskId( QgsTask *task ) const;
443 
449  void cancelAll();
450 
452  bool dependenciesSatisfied( long taskId ) const;
453 
458  QSet< long > dependencies( long taskId ) const SIP_SKIP;
459 
467  QList< QgsMapLayer * > dependentLayers( long taskId ) const;
468 
473  QList< QgsTask * > tasksDependentOnLayer( QgsMapLayer *layer ) const;
474 
479  QList< QgsTask * > activeTasks() const;
480 
486  int countActiveTasks() const;
487 
488  public slots:
489 
494  void triggerTask( QgsTask *task );
495 
496  signals:
497 
503  void progressChanged( long taskId, double progress );
504 
510  void finalTaskProgressChanged( double progress );
511 
517  void statusChanged( long taskId, int status );
518 
523  void taskAdded( long taskId );
524 
529  void taskAboutToBeDeleted( long taskId );
530 
535  void allTasksFinished();
536 
541  void countActiveTasksChanged( int count );
542 
549  void taskTriggered( QgsTask *task );
550 
551  private slots:
552 
553  void taskProgressChanged( double progress );
554  void taskStatusChanged( int status );
555  void layersWillBeRemoved( const QList<QgsMapLayer *> &layers );
556 
557  private:
558 
559  struct TaskInfo
560  {
561  TaskInfo( QgsTask *task = nullptr, int priority = 0 );
562  void createRunnable();
563  QgsTask *task = nullptr;
564  QAtomicInt added;
565  int priority;
566  QgsTaskRunnableWrapper *runnable = nullptr;
567  };
568 
569  mutable QMutex *mTaskMutex;
570 
571  QMap< long, TaskInfo > mTasks;
572  QMap< long, QgsTaskList > mTaskDependencies;
573  QMap< long, QgsWeakMapLayerPointerList > mLayerDependencies;
574 
576  long mNextTaskId = 1;
577 
579  QSet< QgsTask * > mActiveTasks;
581  QSet< QgsTask * > mParentTasks;
583  QSet< QgsTask * > mSubTasks;
584 
585  QSet< QgsTask * > mPendingDeletion;
586 
587  long addTaskPrivate( QgsTask *task,
588  QgsTaskList dependencies,
589  bool isSubTask,
590  int priority );
591 
592  bool cleanupAndDeleteTask( QgsTask *task );
593 
598  void processQueue();
599 
605  void cancelDependentTasks( long taskId );
606 
607  bool resolveDependencies( long firstTaskId, long currentTaskId, QSet< long > &results ) const;
608 
610  bool hasCircularDependencies( long taskId ) const;
611 
612  friend class TestQgsTaskManager;
613 };
614 
615 #endif //QGSTASKMANAGER_H
Base class for all map layer types.
Definition: qgsmaplayer.h:61
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:1392
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.