QGIS API Documentation  3.10.0-A Coruña (6c816b4204)
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 
95  void setDescription( const QString &description );
96 
100  bool canCancel() const { return mFlags & CanCancel; }
101 
106  bool isActive() const { return mOverallStatus == Running; }
107 
111  TaskStatus status() const { return mOverallStatus; }
112 
116  QString description() const { return mDescription; }
117 
121  double progress() const { return mTotalProgress; }
122 
130  qint64 elapsedTime() const;
131 
141  virtual void cancel();
142 
150  void hold();
151 
158  void unhold();
159 
162  {
163  SubTaskIndependent = 0,
165  };
166 
187  void addSubTask( QgsTask *subTask SIP_TRANSFER, const QgsTaskList &dependencies = QgsTaskList(),
188  SubTaskDependency subTaskDependency = SubTaskIndependent );
189 
195  void setDependentLayers( const QList<QgsMapLayer *> &dependentLayers );
196 
202  QList< QgsMapLayer * > dependentLayers() const;
203 
213  bool waitForFinished( int timeout = 30000 );
214 
215  signals:
216 
223  void progressChanged( double progress );
224 
231  void statusChanged( int status );
232 
238  void begun();
239 
245  void taskCompleted();
246 
254  void taskTerminated();
255 
256  protected:
257 
266  virtual bool run() = 0;
267 
278  virtual void finished( bool result ) { Q_UNUSED( result ) }
279 
285  bool isCanceled() const { return mShouldTerminate; }
286 
287  protected slots:
288 
294  void setProgress( double progress );
295 
296  private slots:
297  void subTaskStatusChanged( int status );
298 
299  private:
300 
301  Flags mFlags;
302  QString mDescription;
304  TaskStatus mStatus = Queued;
306  TaskStatus mOverallStatus = Queued;
307 
312  QMutex mNotFinishedMutex;
313 
315  double mProgress = 0.0;
317  double mTotalProgress = 0.0;
318  bool mShouldTerminate = false;
319  int mStartCount = 0;
320 
321  struct SubTask
322  {
323  SubTask( QgsTask *task, const QgsTaskList &dependencies, SubTaskDependency dependency )
324  : task( task )
325  , dependencies( dependencies )
326  , dependency( dependency )
327  {}
328  QgsTask *task = nullptr;
329  QgsTaskList dependencies;
330  SubTaskDependency dependency;
331  };
332  QList< SubTask > mSubTasks;
333 
334  QgsWeakMapLayerPointerList mDependentLayers;
335 
336  QElapsedTimer mElapsedTime;
337 
338 
342  void start();
343 
347  void completed();
348 
352  void terminated();
353 
354  void processSubTasksForCompletion();
355 
356  void processSubTasksForTermination();
357 
358  void processSubTasksForHold();
359 
360  friend class QgsTaskManager;
361  friend class QgsTaskRunnableWrapper;
362  friend class TestQgsTaskManager;
363 
364 };
365 
366 
367 Q_DECLARE_OPERATORS_FOR_FLAGS( QgsTask::Flags )
368 
369 
376 class CORE_EXPORT QgsTaskManager : public QObject
377 {
378  Q_OBJECT
379 
380  public:
381 
386  QgsTaskManager( QObject *parent SIP_TRANSFERTHIS = nullptr );
387 
388  ~QgsTaskManager() override;
389 
394  {
395 
400  explicit TaskDefinition( QgsTask *task, const QgsTaskList &dependentTasks = QgsTaskList() )
401  : task( task )
402  , dependentTasks( dependentTasks )
403  {}
404 
406  QgsTask *task = nullptr;
407 
414 
415  };
416 
425  long addTask( QgsTask *task SIP_TRANSFER, int priority = 0 );
426 
435  long addTask( const TaskDefinition &task SIP_TRANSFER, int priority = 0 );
436 
442  QgsTask *task( long id ) const;
443 
447  QList<QgsTask *> tasks() const;
448 
450  int count() const;
451 
457  long taskId( QgsTask *task ) const;
458 
464  void cancelAll();
465 
467  bool dependenciesSatisfied( long taskId ) const;
468 
473  QSet< long > dependencies( long taskId ) const SIP_SKIP;
474 
482  QList< QgsMapLayer * > dependentLayers( long taskId ) const;
483 
488  QList< QgsTask * > tasksDependentOnLayer( QgsMapLayer *layer ) const;
489 
494  QList< QgsTask * > activeTasks() const;
495 
501  int countActiveTasks() const;
502 
503  public slots:
504 
509  void triggerTask( QgsTask *task );
510 
511  signals:
512 
518  void progressChanged( long taskId, double progress );
519 
525  void finalTaskProgressChanged( double progress );
526 
532  void statusChanged( long taskId, int status );
533 
538  void taskAdded( long taskId );
539 
544  void taskAboutToBeDeleted( long taskId );
545 
550  void allTasksFinished();
551 
556  void countActiveTasksChanged( int count );
557 
564  void taskTriggered( QgsTask *task );
565 
566  private slots:
567 
568  void taskProgressChanged( double progress );
569  void taskStatusChanged( int status );
570  void layersWillBeRemoved( const QList<QgsMapLayer *> &layers );
571 
572  private:
573 
574  struct TaskInfo
575  {
576  TaskInfo( QgsTask *task = nullptr, int priority = 0 );
577  void createRunnable();
578  QgsTask *task = nullptr;
579  QAtomicInt added;
580  int priority;
581  QgsTaskRunnableWrapper *runnable = nullptr;
582  };
583 
584  mutable QMutex *mTaskMutex;
585 
586  QMap< long, TaskInfo > mTasks;
587  QMap< long, QgsTaskList > mTaskDependencies;
588  QMap< long, QgsWeakMapLayerPointerList > mLayerDependencies;
589 
591  long mNextTaskId = 1;
592 
594  QSet< QgsTask * > mActiveTasks;
596  QSet< QgsTask * > mParentTasks;
598  QSet< QgsTask * > mSubTasks;
599 
600  QSet< QgsTask * > mPendingDeletion;
601 
602  long addTaskPrivate( QgsTask *task,
603  QgsTaskList dependencies,
604  bool isSubTask,
605  int priority );
606 
607  bool cleanupAndDeleteTask( QgsTask *task );
608 
613  void processQueue();
614 
620  void cancelDependentTasks( long taskId );
621 
622  bool resolveDependencies( long firstTaskId, long currentTaskId, QSet< long > &results ) const;
623 
625  bool hasCircularDependencies( long taskId ) const;
626 
627  friend class TestQgsTaskManager;
628 };
629 
630 #endif //QGSTASKMANAGER_H
Base class for all map layer types.
Definition: qgsmaplayer.h:79
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:53
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:126
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:1639
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.