[Development] A QtCore class for event-driven jobs

Matt Broadstone mbroadst at gmail.com
Fri Sep 6 19:56:51 CEST 2013


On Fri, Sep 6, 2013 at 1:52 PM, David Faure <david.faure at kdab.com> wrote:

> I would like to propose the inclusion of a QJob class in QtCore, based on
> years of experience with KIO::Job and KJob.
>
> The idea is to encapsulate an event driven asynchronous operation into a
> job
> class. Example use cases:
> - a network download with QNetworkAccessManager.
> - operations (command+reply) over a QLocalSocket or QTcpSocket (like
> akonadi).
> - long async dbus calls (special case of the previous line)
> - long tasks executed by external processes (e.g. "make" from an IDE,
> "unrar"
> from an archive program)
> ...
>
> At the core, QJob is really just a class with start() and kill(), calling
> pure
> virtual methods doStart() and doKill(), and signals, most importantly the
> result(QJob *) signal.
>
> The expected use case is:
>
>  void SomeClass::methodWithAsynchronousJobCall()
>  {
>    QJob* job = someoperation(some parameters);
>    connect(job, SIGNAL(result(QJob*)),
>            this, SLOT(handleResult(QJob*)));
>    job->start(); // or it could just autostart, which I actually prefer...
>  }
>    (other connects, specific to the job)
>
>  And handleResult is usually at least:
>
>  void SomeClass::handleResult( QJob *job )
>  {
>    if (job->error()) {
>        // handle error
>    } else {
>       // handle succesful job completion, if needed
>    }
>  }
>
> But it can and should also have the following features:
> * error code, error text
> * suspend/resume with doSuspend/doResume virtual methods
> * capabilities Killable and Suspendable, to avoid trying these on jobs that
> don't support them
> * kill(Quietly) vs kill(EmitResult), for the app's convenience
> * a finished signal that is emitted with both types of killing, for things
> like progress dialogs
> * auto-deletion (on by default, can be turned off)
> * synchronous exec() using a QEventLoop, with a big fat huge warning about
> not
> using that in GUI apps (ideally only to be used in unittests or separate
> threads).
> * more standard signals for progress info, messages, warnings..
>
> The whole point of standardizing such signals is that it allows generic
> GUIs
> to be built on top, so that your app or your desktop can show the progress
> of
> multiple concurrent jobs, of different types (file download, CD burning,
> mail
> checking, etc. etc.)
>
> Finally, for the benefit of job implementors, QJob would support sub-jobs.
> The job implementation would choose when to create these subjobs (all at
> once
> initially, to have them run in parallel, or one after the other, for
> sequence
> of operations). KDE currently does that in a subclass (KCompositeJob) but
> Thiago and I (and kio, and akonadi) agree that it's better to have it all
> in
> one class instead.
>
> We also have a standard interface for error handling so that all jobs from
> a
> given framework can have their error handled the same way, but thinking
> about
> it, that part could stay separate, at least for now.
>
> Well, that's it. So why this email? Because Thiago asked me to, and to
> gather
> some support. I plan to make a merge request for Qt 5.2.
>
> Thiago asked more specifically:
>
> * API-wise, can't this be merged with QFuture?
> -> no, because QFuture encapsulates a value, with blocking methods for
> getting
> the value, even available as casting-to-the-value. If we imagine a QFuture
> that wraps a QJob, and the blocking method calling exec(), we'd have a lot
> more nested event loops than is good for the health of our programs.
> On the other hand, QJob would not be related to any value. It's really a
> QObject that informs of progress via signals.
>
> * relation to QRunnable?
> A runnable is also some sort of "job", but the implementation is completely
> different: a runnable is one sync method, while a qjob is all signals/slots
> based, with start() returning immediately. So one can't be used like the
> other, a given task implementation is either a blocking task for a thread
> with
> no event loop (QRunnable) or an async task that can actually be used in any
> thread with an event loop.
>
> * relation to QNetworkReply?
> If that one didn't exist yet, we'd definitely write it as a QJob subclass.
> So
> instead, I propose to wrap QNetworkReply into a QNetworkJob or something,
> in
> order to offer the QJob interface for QNAM requests. On one hand this
> doesn't
> have to go in at the same time as QJob itself, but OTOH it could be a real-
> world testcase for it, proving its usefulness and correctness...
>
> Any other questions?
>
>
+1, or more if possible :)

Is this code up somewhere already for early review? This is very much
needed in Qt imho, I imagine it's one of those patterns that people roll
themselves in many cases.

Matt


> --
> David Faure | david.faure at kdab.com | Managing Director KDAB France
> KDAB (France) S.A.S., a KDAB Group company
> Tel. France +33 (0)4 90 84 08 53, Sweden (HQ) +46-563-540090
> KDAB - Qt Experts - Platform-independent software solutions
>
> _______________________________________________
> Development mailing list
> Development at qt-project.org
> http://lists.qt-project.org/mailman/listinfo/development
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.qt-project.org/pipermail/development/attachments/20130906/373e39b2/attachment.html>


More information about the Development mailing list