QGIS API Documentation  3.17.0-Master (8af46bc54f)
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
Base class for all map layer types.
Definition: qgsmaplayer.h:83
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.
Q_DECLARE_OPERATORS_FOR_FLAGS(QgsField::ConfigurationFlags) CORE_EXPORT QDataStream &operator<<(QDataStream &out
Writes the field to stream out. QGIS version compatibility is not guaranteed.
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:1744
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.