QGIS API Documentation  3.21.0-Master (2d5a580dfc)
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  AllFlags = CanCancel,
77  };
78  Q_DECLARE_FLAGS( Flags, Flag )
79 
80 
85  QgsTask( const QString &description = QString(), QgsTask::Flags flags = AllFlags );
86 
87  ~QgsTask() override;
88 
92  Flags flags() const { return mFlags; }
93 
99  void setDescription( const QString &description );
100 
104  bool canCancel() const { return mFlags & CanCancel; }
105 
110  bool isActive() const { return mOverallStatus == Running; }
111 
115  TaskStatus status() const { return mOverallStatus; }
116 
120  QString description() const { return mDescription; }
121 
125  double progress() const { return mTotalProgress; }
126 
134  qint64 elapsedTime() const;
135 
145  virtual void cancel();
146 
154  void hold();
155 
162  void unhold();
163 
166  {
167  SubTaskIndependent = 0,
169  };
170 
191  void addSubTask( QgsTask *subTask SIP_TRANSFER, const QgsTaskList &dependencies = QgsTaskList(),
192  SubTaskDependency subTaskDependency = SubTaskIndependent );
193 
199  void setDependentLayers( const QList<QgsMapLayer *> &dependentLayers );
200 
206  QList< QgsMapLayer * > dependentLayers() const;
207 
217  bool waitForFinished( int timeout = 30000 );
218 
219  signals:
220 
227  void progressChanged( double progress );
228 
235  void statusChanged( int status );
236 
242  void begun();
243 
250 
259 
260  protected:
261 
270  virtual bool run() = 0;
271 
282  virtual void finished( bool result ) { Q_UNUSED( result ) }
283 
289  bool isCanceled() const;
290 
291  protected slots:
292 
298  void setProgress( double progress );
299 
300  private slots:
301  void subTaskStatusChanged( int status );
302 
303  private:
304 
305  Flags mFlags;
306  QString mDescription;
308  TaskStatus mStatus = Queued;
310  TaskStatus mOverallStatus = Queued;
311 
316  QMutex mNotFinishedMutex;
317 
322  QSemaphore mNotStartedMutex;
323 
325  double mProgress = 0.0;
327  double mTotalProgress = 0.0;
328  bool mShouldTerminate = false;
329  mutable QMutex mShouldTerminateMutex;
330  int mStartCount = 0;
331 
332  struct SubTask
333  {
334  SubTask( QgsTask *task, const QgsTaskList &dependencies, SubTaskDependency dependency )
335  : task( task )
336  , dependencies( dependencies )
337  , dependency( dependency )
338  {}
339  QgsTask *task = nullptr;
340  QgsTaskList dependencies;
341  SubTaskDependency dependency;
342  };
343  QList< SubTask > mSubTasks;
344 
345  QgsWeakMapLayerPointerList mDependentLayers;
346 
347  QElapsedTimer mElapsedTime;
348 
349 
353  void start();
354 
358  void completed();
359 
363  void terminated();
364 
365 
366  void processSubTasksForHold();
367 
368  friend class QgsTaskManager;
369  friend class QgsTaskRunnableWrapper;
370  friend class TestQgsTaskManager;
371 
372  private slots:
373 
374  void processSubTasksForCompletion();
375 
376  void processSubTasksForTermination();
377 
378 };
379 
380 
381 Q_DECLARE_OPERATORS_FOR_FLAGS( QgsTask::Flags )
382 
383 
390 class CORE_EXPORT QgsTaskManager : public QObject
391 {
392  Q_OBJECT
393 
394  public:
395 
400  QgsTaskManager( QObject *parent SIP_TRANSFERTHIS = nullptr );
401 
402  ~QgsTaskManager() override;
403 
408  {
409 
414  explicit TaskDefinition( QgsTask *task, const QgsTaskList &dependentTasks = QgsTaskList() )
415  : task( task )
416  , dependentTasks( dependentTasks )
417  {}
418 
420  QgsTask *task = nullptr;
421 
428 
429  };
430 
439  long addTask( QgsTask *task SIP_TRANSFER, int priority = 0 );
440 
449  long addTask( const TaskDefinition &task SIP_TRANSFER, int priority = 0 );
450 
456  QgsTask *task( long id ) const;
457 
461  QList<QgsTask *> tasks() const;
462 
464  int count() const;
465 
471  long taskId( QgsTask *task ) const;
472 
478  void cancelAll();
479 
481  bool dependenciesSatisfied( long taskId ) const;
482 
487  QSet< long > dependencies( long taskId ) const SIP_SKIP;
488 
496  QList< QgsMapLayer * > dependentLayers( long taskId ) const;
497 
502  QList< QgsTask * > tasksDependentOnLayer( QgsMapLayer *layer ) const;
503 
508  QList< QgsTask * > activeTasks() const;
509 
515  int countActiveTasks() const;
516 
517  public slots:
518 
523  void triggerTask( QgsTask *task );
524 
525  signals:
526 
532  void progressChanged( long taskId, double progress );
533 
539  void finalTaskProgressChanged( double progress );
540 
546  void statusChanged( long taskId, int status );
547 
552  void taskAdded( long taskId );
553 
558  void taskAboutToBeDeleted( long taskId );
559 
565 
570  void countActiveTasksChanged( int count );
571 
578  void taskTriggered( QgsTask *task );
579 
580  private slots:
581 
582  void taskProgressChanged( double progress );
583  void taskStatusChanged( int status );
584  void layersWillBeRemoved( const QList<QgsMapLayer *> &layers );
585 
586  private:
587 
588  struct TaskInfo
589  {
590  TaskInfo( QgsTask *task = nullptr, int priority = 0 );
591  void createRunnable();
592  QgsTask *task = nullptr;
593  QAtomicInt added;
594  int priority;
595  QgsTaskRunnableWrapper *runnable = nullptr;
596  };
597 
598  bool mInitialized = false;
599 
600 #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
601  mutable QMutex *mTaskMutex;
602 #else
603  mutable QRecursiveMutex *mTaskMutex;
604 #endif
605 
606  QMap< long, TaskInfo > mTasks;
607  QMap< long, QgsTaskList > mTaskDependencies;
608  QMap< long, QgsWeakMapLayerPointerList > mLayerDependencies;
609 
611  long mNextTaskId = 1;
612 
614  QSet< QgsTask * > mActiveTasks;
616  QSet< QgsTask * > mParentTasks;
618  QSet< QgsTask * > mSubTasks;
619 
620  QSet< QgsTask * > mPendingDeletion;
621 
622  long addTaskPrivate( QgsTask *task,
623  QgsTaskList dependencies,
624  bool isSubTask,
625  int priority );
626 
627  bool cleanupAndDeleteTask( QgsTask *task );
628 
633  void processQueue();
634 
640  void cancelDependentTasks( long taskId );
641 
642  bool resolveDependencies( long firstTaskId, long currentTaskId, QSet< long > &results ) const;
643 
645  bool hasCircularDependencies( long taskId ) const;
646 
647  friend class TestQgsTaskManager;
648 };
649 
650 #endif //QGSTASKMANAGER_H
Base class for all map layer types.
Definition: qgsmaplayer.h:71
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:2112
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.