QGIS API Documentation  3.12.1-BucureČ™ti (121cc00ff0)
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  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 
96  void setDescription( const QString &description );
97 
101  bool canCancel() const { return mFlags & CanCancel; }
102 
107  bool isActive() const { return mOverallStatus == Running; }
108 
112  TaskStatus status() const { return mOverallStatus; }
113 
117  QString description() const { return mDescription; }
118 
122  double progress() const { return mTotalProgress; }
123 
131  qint64 elapsedTime() const;
132 
142  virtual void cancel();
143 
151  void hold();
152 
159  void unhold();
160 
163  {
164  SubTaskIndependent = 0,
166  };
167 
188  void addSubTask( QgsTask *subTask SIP_TRANSFER, const QgsTaskList &dependencies = QgsTaskList(),
189  SubTaskDependency subTaskDependency = SubTaskIndependent );
190 
196  void setDependentLayers( const QList<QgsMapLayer *> &dependentLayers );
197 
203  QList< QgsMapLayer * > dependentLayers() const;
204 
214  bool waitForFinished( int timeout = 30000 );
215 
216  signals:
217 
224  void progressChanged( double progress );
225 
232  void statusChanged( int status );
233 
239  void begun();
240 
246  void taskCompleted();
247 
255  void taskTerminated();
256 
257  protected:
258 
267  virtual bool run() = 0;
268 
279  virtual void finished( bool result ) { Q_UNUSED( result ) }
280 
286  bool isCanceled() const { return mShouldTerminate; }
287 
288  protected slots:
289 
295  void setProgress( double progress );
296 
297  private slots:
298  void subTaskStatusChanged( int status );
299 
300  private:
301 
302  Flags mFlags;
303  QString mDescription;
305  TaskStatus mStatus = Queued;
307  TaskStatus mOverallStatus = Queued;
308 
313  QMutex mNotFinishedMutex;
314 
319  QSemaphore mNotStartedMutex;
320 
322  double mProgress = 0.0;
324  double mTotalProgress = 0.0;
325  bool mShouldTerminate = false;
326  int mStartCount = 0;
327 
328  struct SubTask
329  {
330  SubTask( QgsTask *task, const QgsTaskList &dependencies, SubTaskDependency dependency )
331  : task( task )
332  , dependencies( dependencies )
333  , dependency( dependency )
334  {}
335  QgsTask *task = nullptr;
336  QgsTaskList dependencies;
337  SubTaskDependency dependency;
338  };
339  QList< SubTask > mSubTasks;
340 
341  QgsWeakMapLayerPointerList mDependentLayers;
342 
343  QElapsedTimer mElapsedTime;
344 
345 
349  void start();
350 
354  void completed();
355 
359  void terminated();
360 
361  void processSubTasksForCompletion();
362 
363  void processSubTasksForTermination();
364 
365  void processSubTasksForHold();
366 
367  friend class QgsTaskManager;
368  friend class QgsTaskRunnableWrapper;
369  friend class TestQgsTaskManager;
370 
371 };
372 
373 
374 Q_DECLARE_OPERATORS_FOR_FLAGS( QgsTask::Flags )
375 
376 
383 class CORE_EXPORT QgsTaskManager : public QObject
384 {
385  Q_OBJECT
386 
387  public:
388 
393  QgsTaskManager( QObject *parent SIP_TRANSFERTHIS = nullptr );
394 
395  ~QgsTaskManager() override;
396 
401  {
402 
407  explicit TaskDefinition( QgsTask *task, const QgsTaskList &dependentTasks = QgsTaskList() )
408  : task( task )
409  , dependentTasks( dependentTasks )
410  {}
411 
413  QgsTask *task = nullptr;
414 
421 
422  };
423 
432  long addTask( QgsTask *task SIP_TRANSFER, int priority = 0 );
433 
442  long addTask( const TaskDefinition &task SIP_TRANSFER, int priority = 0 );
443 
449  QgsTask *task( long id ) const;
450 
454  QList<QgsTask *> tasks() const;
455 
457  int count() const;
458 
464  long taskId( QgsTask *task ) const;
465 
471  void cancelAll();
472 
474  bool dependenciesSatisfied( long taskId ) const;
475 
480  QSet< long > dependencies( long taskId ) const SIP_SKIP;
481 
489  QList< QgsMapLayer * > dependentLayers( long taskId ) const;
490 
495  QList< QgsTask * > tasksDependentOnLayer( QgsMapLayer *layer ) const;
496 
501  QList< QgsTask * > activeTasks() const;
502 
508  int countActiveTasks() const;
509 
510  public slots:
511 
516  void triggerTask( QgsTask *task );
517 
518  signals:
519 
525  void progressChanged( long taskId, double progress );
526 
532  void finalTaskProgressChanged( double progress );
533 
539  void statusChanged( long taskId, int status );
540 
545  void taskAdded( long taskId );
546 
551  void taskAboutToBeDeleted( long taskId );
552 
557  void allTasksFinished();
558 
563  void countActiveTasksChanged( int count );
564 
571  void taskTriggered( QgsTask *task );
572 
573  private slots:
574 
575  void taskProgressChanged( double progress );
576  void taskStatusChanged( int status );
577  void layersWillBeRemoved( const QList<QgsMapLayer *> &layers );
578 
579  private:
580 
581  struct TaskInfo
582  {
583  TaskInfo( QgsTask *task = nullptr, int priority = 0 );
584  void createRunnable();
585  QgsTask *task = nullptr;
586  QAtomicInt added;
587  int priority;
588  QgsTaskRunnableWrapper *runnable = nullptr;
589  };
590 
591  mutable QMutex *mTaskMutex;
592 
593  QMap< long, TaskInfo > mTasks;
594  QMap< long, QgsTaskList > mTaskDependencies;
595  QMap< long, QgsWeakMapLayerPointerList > mLayerDependencies;
596 
598  long mNextTaskId = 1;
599 
601  QSet< QgsTask * > mActiveTasks;
603  QSet< QgsTask * > mParentTasks;
605  QSet< QgsTask * > mSubTasks;
606 
607  QSet< QgsTask * > mPendingDeletion;
608 
609  long addTaskPrivate( QgsTask *task,
610  QgsTaskList dependencies,
611  bool isSubTask,
612  int priority );
613 
614  bool cleanupAndDeleteTask( QgsTask *task );
615 
620  void processQueue();
621 
627  void cancelDependentTasks( long taskId );
628 
629  bool resolveDependencies( long firstTaskId, long currentTaskId, QSet< long > &results ) const;
630 
632  bool hasCircularDependencies( long taskId ) const;
633 
634  friend class TestQgsTaskManager;
635 };
636 
637 #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:1657
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.