[Interest] QFuture, QAsync? Coroutines, Generators, Promises, Futures...

Ben Lau xbenlau at gmail.com
Wed Mar 22 08:54:01 CET 2017


On 31 December 2016 at 21:10, Ben Lau <xbenlau at gmail.com> wrote:

>
>
> On 28 December 2016 at 16:36, Petar Koretić <petar.koretic at gmail.com>
> wrote:
>
>>
>>
>> On Wed, Dec 28, 2016 at 4:51 AM, Ben Lau <xbenlau at gmail.com> wrote:
>>
>>>
>>>
>>> On 28 December 2016 at 05:50, Petar Koretić <petar.koretic at gmail.com>
>>> wrote:
>>>
>>>> Hi all!
>>>>
>>>> In the wild people are doing all kinds of different things with Qt on
>>>> the network side. And there are some obvious issues with that given the
>>>> "callback" nature of Qt networking code.
>>>>
>>>> One can see different examples of people over the years dealing with
>>>> that:
>>>>
>>>> http://cukic.co/2016/01/17/asynqt-framework-making-qfuture-useful
>>>> https://github.com/KDE/kasync
>>>> http://qasync.henrikhedberg.com
>>>> https://github.com/mhogomchungu/tasks
>>>> https://gist.github.com/legnaleurc/1038309
>>>>
>>>> Since we are also using Qt a lot on the server side I'm curious what is
>>>> the progress from the Qt side on that given that coroutines will come to
>>>> C++ (http://en.cppreference.com/w/cpp/experimental)
>>>>
>>>> We were using Boost and as we were using Qt for clients decided we
>>>> could also do server parts in Qt as well. This is all fine and I enjoyed
>>>> it, but boost has futures, promises and coroutines as well, which is nice,
>>>> since we also have backends in Node.js where we employ identical patterns.
>>>>
>>>> So I've been waiting for 2 years now to see what will come up from Qt
>>>> and I don't see much about that changing. Heck, QAsync tackled this in 2011.
>>>> Will Qt "embrace" coroutines from standard? Will they come up with
>>>> something of their own? Should we abandon Qt for networking? Should we use
>>>> something of our own?
>>>>
>>>> One possible way currently is to use QtConcurrent (badly I guess) and
>>>> wrap everything into QtConcurrent::run, which, for example, for
>>>> QNetworkRequest means first converting it to sync code using local event
>>>> loop which is again not recommended.
>>>>
>>>>
>>> Why you think it is not recommended?
>>>
>>>
>> This was once on http://developer.nokia.com/com
>> munity/wiki/How_to_wait_synchronously_for_a_Signal_in_Qt
>> Local QEventloop may cause out of control recursion or deadlocks in some
>> cases. Whenever I had idea to use it, nobody recommended it. Quick google
>> search now will tell you the same.
>>
>> Nevertheless, for example, QNetworkRequest is explicitly asynchronous
>> while QSqlDatabase is explicitly synchronous. I'm just expecting that
>> somebody is doing the same these days with Qt and want to improve on that
>> given that C++ itself will get "async" support so I want to avoid any
>> duplication from my side. I'm not talking about something new, just asking
>> if there are any plans in that direction.
>>
>>
>>>
>>>>
>
> I think a topic is not well discussed do not mean it is not recommended. I
> am using QtConcurrent for handling asynchronous task. So far I have
> encountered deadlock issue only once. It happen when the application quit
> but the task is not finished yet.
>
> Coroutine should be a good solution for many problems. I may switch to
> coroutine if the task is not CPU intensive.  But unfortunately that it is
> not available in Qt yet. So user need an alternative solution. It can't
> just wait for new version of Qt. QtConcurrent may not be a bad choice. It
> should be worth to discuss.
>
> I am not sure is any Qt developer working on coroutine yet. I think it is
> better to ask in developer mailing list.
>
>
I have created a library called AsyncFuture that could convert a signal
into a QFuture and use it like a Promise object in Javascript. (It is not
obtained from QtConcurrent::run) That show how QFuture can be used in
asynchronous programming.

https://github.com/benlau/asyncfuture

For example:

===
QFuture<void> future = observe(timer, &QTimer::timeout).future();

/* Listen from the future without using QFutureWatcher<T>*/
observe(future).subscribe([]() {
    // onCompleted. It is invoked when the observed future is finished
successfully
    qDebug() << "onCompleted";
},[]() {
    // onCanceled
    qDebug() << "onCancel";
});
===

Make a deferred future, finish a future without using signal

===

auto d = deferred<bool>();

observe(d.future()).subscribe([]() {
    qDebug() << "onCompleted";
}, []() {
    qDebug() << "onCancel";
});

QVERIFY(d.future().isFinished, false);
d.complete(true); // or d.cancel();
QVERIFY(d.future().isFinished, true);

===

Ofcoz, I won't say it is a better solution than async. What it provides is
just a Promise-level asynchronous programming interface. But that could
handle QNetworkRequest (signal -> QFuture) and QSqlDatabase
(QtConcurrent::run)  using the same mechanism of QFuture.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.qt-project.org/pipermail/interest/attachments/20170322/3493e665/attachment.html>


More information about the Interest mailing list