[Development] Evolving Qt's multithreading API
André Somers
andre at familiesomers.nl
Mon Mar 4 17:25:35 CET 2013
Op 4-3-2013 16:17, Sze Howe Koh schreef:
> On 2 March 2013 18:17, Andre Somers <andre at familiesomers.nl> wrote:
>> Actually, how do you feel about adding an optional _then_ argument to
>> the list of arguments of the functions in QtConcurrent and whatever is
>> decided to replace the QtConcurrent::run feature? Such a _then_ argument
>> could be a slot signature, a function pointer or a lambda function
>> (basically, whatever you can use in the Qt 5 QObject::connect). That
>> would make it quite a bit easier to work with, I think. It would
>> eliminate the need to create (and delete) a QFutureWatcher for a lot of
>> cases. The method you passed into the _then_ argument would be called
>> when the future is ready. It would be very nice if the _then_ argument
>> could optionally have an argument of the return type of QFuture::result.
>>
>> For this to work, QFuture would not need to be a QObject itself, and
>> because you pass in the _then_ argument with the call itself, you don't
>> have the race issues that you get if you need to connect in separate
>> calls after you have already fired off the thread: no need for
>> trampoline objects or the like.
> Do you mean like the last argument to QTimer::singleShot()? (this
> needs to be updated to support Qt 5 slots, by the way)
Yes, very much like that, but updated to also support the Qt5 like way
of connecting.
> Yes, that could work. To make it truly optional though, the main
> parallel function would have to be pre-bound by the programmer (e.g.
> using https://codereview.qt-project.org/#change,45294), since the
> argument list is variable-size.
>
> QFuture<T> runFunction(QFunction<T> main, QFunction<S> then = NullFunction);
>
> Would the extra binding step nullify the convenience of not requiring
> a signalling object?
It would not quite, but it would be a bit of a let-down. There still is
the benefit of not having to worry about race conditions. However, if we
modify the syntax a little bit, I think we can avoid the additional
binding step:
QFuture<T> runFunction(QFunction<T> then, QFunction<T> main);
QFuture<T> runFunction(QFuntion<void> then, QFuntion<T> main);
QFuture<T> runFunction(QFunction<T> main);
(Copying your use of QFunction, a quick look at the WIP you mentioned
doesn't quite reveal to me how it is supposed to work, and I probably
use it wrong. The then argument could be lambda function, a QObject* and
a slot signature, a pointer to an object and a member function pointer,
or perhaps even a plain function pointer. It would be nice if the
argument for these could be either no argument at all, or of the type T
so it can just receive the value from the method.)
Sure, it would read easier to have the _then_ follow the actual method,
if if that is not possible, then I would not mind having them be reversed.
However - and I am not a template mage - I think it should be possible
to keep the order as is? As long as the actual function doesn't take a
final argument with the given signature, I don't think there would be
confusion?
Note that I'd also like to see the same possibity for the other
QtConcurrent methods, and pershaps even the threadpool method as well.
> Or, what if the run-function returns a QFutureWatcher which already
> has a QFuture attached -- would that ease the burden from the
> programmer a bit?
No, it would not!
The returned QFutureWatcher then has unclear ownership. That sounds even
worse than having to create one yourself. And: the future still can
finish before you have a chance to make the connection between the
QFutureWatcher::finished() signal and your own slot.
> It's such a shame that template classes can't be meta-objects...
> otherwise we could emit the return value directly. That would truly be
> event-driven C++!
Yeah, that is a very unfortunate artifact of the way Qt implements
signals and slots. However, it is what it is...
André
More information about the Development
mailing list