Skip to content

Commit 297b572

Browse files
committed
QgsTask is no longer a QRunnable
Instead use a private wrapper class to make QgsTask compatible with QThreadPool
1 parent 29f310c commit 297b572

File tree

5 files changed

+68
-33
lines changed

5 files changed

+68
-33
lines changed

python/core/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ def __init__(self, description, flags, function, on_finished, *args, **kwargs):
208208
self.returned_values = None
209209
self.exception = None
210210

211-
def _run(self):
211+
def run(self):
212212
try:
213213
self.returned_values = self.function(self, *self.args, **self.kwargs)
214214
except Exception as ex:

python/core/qgstaskmanager.sip

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
*
1515
* \note Added in version 3.0
1616
*/
17-
class QgsTask : QObject, QRunnable
17+
class QgsTask : QObject
1818
{
1919

2020
%TypeHeaderCode
@@ -92,7 +92,7 @@ class QgsTask : QObject, QRunnable
9292
* then this method should not be called directly, instead it is left to the
9393
* task manager to start the task when appropriate.
9494
*/
95-
void run();
95+
void start();
9696

9797
/**
9898
* Notifies the task that it should terminate. Calling this is not guaranteed
@@ -211,7 +211,7 @@ class QgsTask : QObject, QRunnable
211211
* @see completed()
212212
* @see terminated()
213213
*/
214-
virtual TaskResult _run() = 0;
214+
virtual TaskResult run() = 0;
215215

216216
/**
217217
* If the task is managed by a QgsTaskManager, this will be called after the

src/core/qgstaskmanager.cpp

Lines changed: 48 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -34,23 +34,19 @@ QgsTask::QgsTask( const QString &name, const Flags& flags )
3434
, mTotalProgress( 0.0 )
3535
, mShouldTerminate( false )
3636
, mStartCount( 0 )
37-
{
38-
setAutoDelete( false );
39-
}
37+
{}
4038

4139
QgsTask::~QgsTask()
4240
{
4341
Q_ASSERT_X( mStatus != Running, "delete", QString( "status was %1" ).arg( mStatus ).toLatin1() );
4442

45-
QThreadPool::globalInstance()->cancel( this );
46-
4743
Q_FOREACH ( const SubTask& subTask, mSubTasks )
4844
{
4945
delete subTask.task;
5046
}
5147
}
5248

53-
void QgsTask::run()
49+
void QgsTask::start()
5450
{
5551
mStartCount++;
5652
Q_ASSERT( mStartCount == 1 );
@@ -66,7 +62,7 @@ void QgsTask::run()
6662
// force initial emission of progressChanged, but respect if task has had initial progress manually set
6763
setProgress( mProgress );
6864

69-
TaskResult result = _run();
65+
TaskResult result = run();
7066
switch ( result )
7167
{
7268
case ResultSuccess:
@@ -94,7 +90,6 @@ void QgsTask::cancel()
9490

9591
#if QT_VERSION >= 0x050500
9692
//can't cancel queued tasks with qt < 5.5
97-
QThreadPool::globalInstance()->cancel( this );
9893
if ( mStatus == Queued || mStatus == OnHold )
9994
{
10095
// immediately terminate unstarted jobs
@@ -296,6 +291,35 @@ void QgsTask::terminated()
296291
}
297292

298293

294+
///@cond PRIVATE
295+
296+
class QgsTaskRunnableWrapper : public QRunnable
297+
{
298+
public:
299+
300+
QgsTaskRunnableWrapper( QgsTask* task )
301+
: QRunnable()
302+
, mTask( task )
303+
{
304+
setAutoDelete( true );
305+
}
306+
307+
void run() override
308+
{
309+
Q_ASSERT( mTask );
310+
mTask->start();
311+
}
312+
313+
private:
314+
315+
QgsTask* mTask;
316+
317+
};
318+
319+
///@endcond
320+
321+
322+
299323
//
300324
// QgsTaskManager
301325
//
@@ -594,6 +618,11 @@ void QgsTaskManager::taskStatusChanged( int status )
594618
if ( id < 0 )
595619
return;
596620

621+
#if QT_VERSION >= 0x050500
622+
QgsTaskRunnableWrapper* runnable = mTasks.value( id ).runnable;
623+
QThreadPool::globalInstance()->cancel( runnable );
624+
#endif
625+
597626
if ( status == QgsTask::Terminated || status == QgsTask::Complete )
598627
{
599628
QgsTask::TaskResult result = status == QgsTask::Complete ? QgsTask::ResultSuccess
@@ -665,6 +694,8 @@ bool QgsTaskManager::cleanupAndDeleteTask( QgsTask *task )
665694
if ( id < 0 )
666695
return false;
667696

697+
QgsTaskRunnableWrapper* runnable = mTasks.value( id ).runnable;
698+
668699
task->disconnect( this );
669700

670701
mDependenciesMutex->lockForWrite();
@@ -707,7 +738,7 @@ bool QgsTaskManager::cleanupAndDeleteTask( QgsTask *task )
707738
else
708739
{
709740
#if QT_VERSION >= 0x050500
710-
QThreadPool::globalInstance()->cancel( task );
741+
QThreadPool::globalInstance()->cancel( runnable );
711742
#endif
712743
if ( isParent )
713744
{
@@ -741,7 +772,7 @@ void QgsTaskManager::processQueue()
741772
QgsTask* task = it.value().task;
742773
if ( task && task->mStatus == QgsTask::Queued && dependenciesSatisified( it.key() ) && it.value().added.testAndSetRelaxed( 0, 1 ) )
743774
{
744-
QThreadPool::globalInstance()->start( task, it.value().priority );
775+
QThreadPool::globalInstance()->start( it.value().runnable, it.value().priority );
745776
}
746777

747778
if ( task && ( task->mStatus != QgsTask::Complete && task->mStatus != QgsTask::Terminated ) )
@@ -792,3 +823,10 @@ void QgsTaskManager::cancelDependentTasks( long taskId )
792823
}
793824
}
794825
}
826+
827+
QgsTaskManager::TaskInfo::TaskInfo( QgsTask* task, int priority )
828+
: task( task )
829+
, added( 0 )
830+
, priority( priority )
831+
, runnable( new QgsTaskRunnableWrapper( task ) )
832+
{}

src/core/qgstaskmanager.h

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include <QReadWriteLock>
2525

2626
class QgsTask;
27+
class QgsTaskRunnableWrapper;
2728

2829
//! List of QgsTask objects
2930
typedef QList< QgsTask* > QgsTaskList;
@@ -35,7 +36,7 @@ typedef QList< QgsTask* > QgsTaskList;
3536
* or added to a QgsTaskManager for automatic management.
3637
*
3738
* Derived classes should implement the process they want to execute in the background
38-
* within the _run() method. This method will be called when the
39+
* within the run() method. This method will be called when the
3940
* task commences (ie via calling run() ).
4041
*
4142
* Long running tasks should periodically check the isCancelled() flag to detect if the task
@@ -44,7 +45,7 @@ typedef QList< QgsTask* > QgsTaskList;
4445
*
4546
* \note Added in version 3.0
4647
*/
47-
class CORE_EXPORT QgsTask : public QObject, public QRunnable
48+
class CORE_EXPORT QgsTask : public QObject
4849
{
4950
Q_OBJECT
5051

@@ -122,7 +123,7 @@ class CORE_EXPORT QgsTask : public QObject, public QRunnable
122123
* then this method should not be called directly, instead it is left to the
123124
* task manager to start the task when appropriate.
124125
*/
125-
void run() override;
126+
void start();
126127

127128
/**
128129
* Notifies the task that it should terminate. Calling this is not guaranteed
@@ -242,7 +243,7 @@ class CORE_EXPORT QgsTask : public QObject, public QRunnable
242243
* @see completed()
243244
* @see terminated()
244245
*/
245-
virtual TaskResult _run() = 0;
246+
virtual TaskResult run() = 0;
246247

247248
/**
248249
* If the task is managed by a QgsTaskManager, this will be called after the
@@ -334,7 +335,6 @@ class CORE_EXPORT QgsTask : public QObject, public QRunnable
334335

335336
Q_DECLARE_OPERATORS_FOR_FLAGS( QgsTask::Flags )
336337

337-
338338
/** \ingroup core
339339
* \class QgsTaskManager
340340
* \brief Task manager for managing a set of long-running QgsTask tasks. This class can be created directly,
@@ -496,14 +496,11 @@ class CORE_EXPORT QgsTaskManager : public QObject
496496

497497
struct TaskInfo
498498
{
499-
TaskInfo( QgsTask* task = nullptr, int priority = 0 )
500-
: task( task )
501-
, added( 0 )
502-
, priority( priority )
503-
{}
499+
TaskInfo( QgsTask* task = nullptr, int priority = 0 );
504500
QgsTask* task;
505501
QAtomicInt added;
506502
int priority;
503+
QgsTaskRunnableWrapper* runnable;
507504
};
508505

509506
mutable QReadWriteLock* mTaskMutex;

tests/src/core/testqgstaskmanager.cpp

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ class TestTask : public QgsTask
4040

4141
protected:
4242

43-
TaskResult _run() override
43+
TaskResult run() override
4444
{
4545
runCalled = true;
4646
return ResultPending;
@@ -62,7 +62,7 @@ class TestTerminationTask : public TestTask
6262

6363
protected:
6464

65-
TaskResult _run() override
65+
TaskResult run() override
6666
{
6767
while ( !isCancelled() )
6868
{}
@@ -85,7 +85,7 @@ class CancelableTask : public QgsTask
8585

8686
protected:
8787

88-
TaskResult _run() override
88+
TaskResult run() override
8989
{
9090
while ( !isCancelled() )
9191
{}
@@ -99,7 +99,7 @@ class SuccessTask : public QgsTask
9999

100100
protected:
101101

102-
TaskResult _run() override
102+
TaskResult run() override
103103
{
104104
return ResultSuccess;
105105
}
@@ -111,7 +111,7 @@ class FailTask : public QgsTask
111111

112112
protected:
113113

114-
TaskResult _run() override
114+
TaskResult run() override
115115
{
116116
return ResultFail;
117117
}
@@ -134,7 +134,7 @@ class FinishTask : public QgsTask
134134

135135
protected:
136136

137-
TaskResult _run() override
137+
TaskResult run() override
138138
{
139139
return desiredResult;
140140
}
@@ -218,7 +218,7 @@ void TestQgsTaskManager::task()
218218
QSignalSpy startedSpy( task.data(), &QgsTask::begun );
219219
QSignalSpy statusSpy( task.data(), &QgsTask::statusChanged );
220220

221-
task->run();
221+
task->start();
222222
QCOMPARE( task->status(), QgsTask::Running );
223223
QVERIFY( task->isActive() );
224224
QVERIFY( task->runCalled );
@@ -270,7 +270,7 @@ void TestQgsTaskManager::taskResult()
270270
QCOMPARE( task->status(), QgsTask::Queued );
271271
QSignalSpy statusSpy( task.data(), &QgsTask::statusChanged );
272272

273-
task->run();
273+
task->start();
274274
QCOMPARE( statusSpy.count(), 2 );
275275
QCOMPARE( static_cast< QgsTask::TaskStatus >( statusSpy.at( 0 ).at( 0 ).toInt() ), QgsTask::Running );
276276
QCOMPARE( static_cast< QgsTask::TaskStatus >( statusSpy.at( 1 ).at( 0 ).toInt() ), QgsTask::Complete );
@@ -280,7 +280,7 @@ void TestQgsTaskManager::taskResult()
280280
QCOMPARE( task->status(), QgsTask::Queued );
281281
QSignalSpy statusSpy2( task.data(), &QgsTask::statusChanged );
282282

283-
task->run();
283+
task->start();
284284
QCOMPARE( statusSpy2.count(), 2 );
285285
QCOMPARE( static_cast< QgsTask::TaskStatus >( statusSpy2.at( 0 ).at( 0 ).toInt() ), QgsTask::Running );
286286
QCOMPARE( static_cast< QgsTask::TaskStatus >( statusSpy2.at( 1 ).at( 0 ).toInt() ), QgsTask::Terminated );

0 commit comments

Comments
 (0)