QGIS API Documentation  3.25.0-Master (dec16ba68b)
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 #include <QSemaphore>
27 #include <QElapsedTimer>
28 
29 #include "qgis_core.h"
30 #include "qgsmaplayer.h"
31 
32 class QgsTask;
33 class QgsTaskRunnableWrapper;
34 
36 typedef QList< QgsTask * > QgsTaskList;
37 
54 class CORE_EXPORT QgsTask : public QObject
55 {
56  Q_OBJECT
57 
58  public:
59 
62  {
68  };
69  Q_ENUM( TaskStatus )
70 
71 
72  enum Flag
73  {
74  CanCancel = 1 << 1,
75  CancelWithoutPrompt = 1 << 2,
76  Hidden = 1 << 3,
77  AllFlags = CanCancel,
78  };
79  Q_DECLARE_FLAGS( Flags, Flag )
80 
81 
86  QgsTask( const QString &description = QString(), QgsTask::Flags flags = AllFlags );
87 
88  ~QgsTask() override;
89 
93  Flags flags() const { return mFlags; }
94 
100  void setDescription( const QString &description );
101 
105  bool canCancel() const { return mFlags & CanCancel; }
106 
111  bool isActive() const { return mOverallStatus == Running; }
112 
116  TaskStatus status() const { return mOverallStatus; }
117 
121  QString description() const { return mDescription; }
122 
126  double progress() const { return mTotalProgress; }
127 
135  qint64 elapsedTime() const;
136 
146  virtual void cancel();
147 
155  void hold();
156 
163  void unhold();
164 
167  {
168  SubTaskIndependent = 0,
170  };
171 
192  void addSubTask( QgsTask *subTask SIP_TRANSFER, const QgsTaskList &dependencies = QgsTaskList(),
193  SubTaskDependency subTaskDependency = SubTaskIndependent );
194 
200  void setDependentLayers( const QList<QgsMapLayer *> &dependentLayers );
201 
207  QList< QgsMapLayer * > dependentLayers() const;
208 
218  bool waitForFinished( int timeout = 30000 );
219 
220  signals:
221 
228  void progressChanged( double progress );
229 
236  void statusChanged( int status );
237 
243  void begun();
244 
251 
260 
261  protected:
262 
271  virtual bool run() = 0;
272 
283  virtual void finished( bool result ) { Q_UNUSED( result ) }
284 
290  bool isCanceled() const;
291 
292  protected slots:
293 
299  void setProgress( double progress );
300 
301  private slots:
302  void subTaskStatusChanged( int status );
303 
304  private:
305 
306  Flags mFlags;
307  QString mDescription;
309  TaskStatus mStatus = Queued;
311  TaskStatus mOverallStatus = Queued;
312 
317  QMutex mNotFinishedMutex;
318 
323  QSemaphore mNotStartedMutex;
324 
326  double mProgress = 0.0;
328  double mTotalProgress = 0.0;
329  bool mShouldTerminate = false;
330  mutable QMutex mShouldTerminateMutex;
331  int mStartCount = 0;
332 
333  struct SubTask
334  {
335  SubTask( QgsTask *task, const QgsTaskList &dependencies, SubTaskDependency dependency )
336  : task( task )
337  , dependencies( dependencies )
338  , dependency( dependency )
339  {}
340  QgsTask *task = nullptr;
341  QgsTaskList dependencies;
342  SubTaskDependency dependency;
343  };
344  QList< SubTask > mSubTasks;
345 
346  QgsWeakMapLayerPointerList mDependentLayers;
347 
348  QElapsedTimer mElapsedTime;
349 
350 
354  void start();
355 
359  void completed();
360 
364  void terminated();
365 
366 
367  void processSubTasksForHold();
368 
369  friend class QgsTaskManager;
370  friend class QgsTaskRunnableWrapper;
371  friend class TestQgsTaskManager;
372 
373  private slots:
374 
375  void processSubTasksForCompletion();
376 
377  void processSubTasksForTermination();
378 
379 };
380 
381 
382 Q_DECLARE_OPERATORS_FOR_FLAGS( QgsTask::Flags )
383 
384 
391 class CORE_EXPORT QgsTaskManager : public QObject
392 {
393  Q_OBJECT
394 
395  public:
396 
401  QgsTaskManager( QObject *parent SIP_TRANSFERTHIS = nullptr );
402 
403  ~QgsTaskManager() override;
404 
409  {
410 
415  explicit TaskDefinition( QgsTask *task, const QgsTaskList &dependentTasks = QgsTaskList() )
416  : task( task )
417  , dependentTasks( dependentTasks )
418  {}
419 
421  QgsTask *task = nullptr;
422 
429 
430  };
431 
440  long addTask( QgsTask *task SIP_TRANSFER, int priority = 0 );
441 
450  long addTask( const TaskDefinition &task SIP_TRANSFER, int priority = 0 );
451 
457  QgsTask *task( long id ) const;
458 
462  QList<QgsTask *> tasks() const;
463 
465  int count() const;
466 
472  long taskId( QgsTask *task ) const;
473 
479  void cancelAll();
480 
482  bool dependenciesSatisfied( long taskId ) const;
483 
488  QSet< long > dependencies( long taskId ) const SIP_SKIP;
489 
497  QList< QgsMapLayer * > dependentLayers( long taskId ) const;
498 
503  QList< QgsTask * > tasksDependentOnLayer( QgsMapLayer *layer ) const;
504 
509  QList< QgsTask * > activeTasks() const;
510 
519  int countActiveTasks( bool includeHidden = true ) const;
520 
521  public slots:
522 
527  void triggerTask( QgsTask *task );
528 
529  signals:
530 
536  void progressChanged( long taskId, double progress );
537 
543  void finalTaskProgressChanged( double progress );
544 
550  void statusChanged( long taskId, int status );
551 
556  void taskAdded( long taskId );
557 
562  void taskAboutToBeDeleted( long taskId );
563 
569 
574  void countActiveTasksChanged( int count );
575 
582  void taskTriggered( QgsTask *task );
583 
584  private slots:
585 
586  void taskProgressChanged( double progress );
587  void taskStatusChanged( int status );
588  void layersWillBeRemoved( const QList<QgsMapLayer *> &layers );
589 
590  private:
591 
592  struct TaskInfo
593  {
594  TaskInfo( QgsTask *task = nullptr, int priority = 0 );
595  void createRunnable();
596  QgsTask *task = nullptr;
597  QAtomicInt added;
598  int priority;
599  QgsTaskRunnableWrapper *runnable = nullptr;
600  };
601 
602  bool mInitialized = false;
603 
604 #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
605  mutable QMutex *mTaskMutex;
606 #else
607  mutable QRecursiveMutex *mTaskMutex;
608 #endif
609 
610  QMap< long, TaskInfo > mTasks;
611  QMap< long, QgsTaskList > mTaskDependencies;
612  QMap< long, QgsWeakMapLayerPointerList > mLayerDependencies;
613 
615  long mNextTaskId = 1;
616 
618  QSet< QgsTask * > mActiveTasks;
620  QSet< QgsTask * > mParentTasks;
622  QSet< QgsTask * > mSubTasks;
623 
624  QSet< QgsTask * > mPendingDeletion;
625 
626  long addTaskPrivate( QgsTask *task,
627  QgsTaskList dependencies,
628  bool isSubTask,
629  int priority );
630 
631  bool cleanupAndDeleteTask( QgsTask *task );
632 
637  void processQueue();
638 
644  void cancelDependentTasks( long taskId );
645 
646  bool resolveDependencies( long firstTaskId, long currentTaskId, QSet< long > &results ) const;
647 
649  bool hasCircularDependencies( long taskId ) const;
650 
651  friend class TestQgsTaskManager;
652 };
653 
654 #endif //QGSTASKMANAGER_H
Base class for all map layer types.
Definition: qgsmaplayer.h:73
Task manager for managing a set of long-running QgsTask tasks.
void finalTaskProgressChanged(double progress)
Will be emitted when only a single task remains to complete and that task has reported a progress cha...
void statusChanged(long taskId, int status)
Will be emitted when a task reports a status change.
void taskAdded(long taskId)
Emitted when a new task has been added to the manager.
void taskAboutToBeDeleted(long taskId)
Emitted when a task is about to be deleted.
void allTasksFinished()
Emitted when all tasks are complete.
void progressChanged(long taskId, double progress)
Will be emitted when a task reports a progress change.
void countActiveTasksChanged(int count)
Emitted when the number of active tasks changes.
void taskTriggered(QgsTask *task)
Emitted when a task is triggered.
Abstract base class for long running background tasks.
TaskStatus status() const
Returns the current task status.
Flags flags() const
Returns the flags associated with the task.
void taskCompleted()
Will be emitted by task to indicate its successful completion.
double progress() const
Returns the task's progress (between 0.0 and 100.0)
virtual void finished(bool result)
If the task is managed by a QgsTaskManager, this will be called after the task has finished (whether ...
virtual bool run()=0
Performs the task's operation.
void progressChanged(double progress)
Will be emitted by task when its progress changes.
void begun()
Will be emitted by task to indicate its commencement.
bool isActive() const
Returns true if the task is active, ie it is not complete and has not been canceled.
Flag
Task flags.
void taskTerminated()
Will be emitted by task if it has terminated for any reason other then completion (e....
void statusChanged(int status)
Will be emitted by task when its status changes.
TaskStatus
Status of tasks.
@ Terminated
Task was terminated or errored.
@ Queued
Task is queued and has not begun.
@ OnHold
Task is queued but on hold and will not be started.
@ Running
Task is currently running.
@ Complete
Task successfully completed.
QString description() const
Returns the task's description.
SubTaskDependency
Controls how subtasks relate to their parent task.
@ ParentDependsOnSubTask
Subtask must complete before parent can begin.
bool canCancel() const
Returns true if the task can be canceled.
#define SIP_TRANSFERTHIS
Definition: qgis_sip.h:53
#define SIP_SKIP
Definition: qgis_sip.h:126
#define SIP_TRANSFER
Definition: qgis_sip.h:36
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.
QList< QgsWeakMapLayerPointer > QgsWeakMapLayerPointerList
A list of weak pointers to QgsMapLayers.
Definition: qgsmaplayer.h:2140
QList< QgsTask * > QgsTaskList
List of QgsTask objects.
Definition of a task for inclusion in the manager.
TaskDefinition(QgsTask *task, const QgsTaskList &dependentTasks=QgsTaskList())
Constructor for TaskDefinition.
QgsTaskList dependentTasks
List of dependent tasks which must be completed before task can run.