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

Elvis Stansvik elvstone at gmail.com
Wed Mar 22 09:25:29 CET 2017


2017-03-22 8:54 GMT+01:00 Ben Lau <xbenlau at gmail.com>:
>
>
> 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/community/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.

This looks quite nice. One small API nitpick: I'd change the bool
settleAllMode parameter into SettleMode settleMode with something like

enum SettleMode {
    SettleNone,
    SettleAll
}

since it makes it more obvious what a call does when looking at it
(e.g. combine(true) vs combine(SettleAll)).

Elvis

>
>
>
> _______________________________________________
> Interest mailing list
> Interest at qt-project.org
> http://lists.qt-project.org/mailman/listinfo/interest
>



More information about the Interest mailing list