[Development] Evolving Qt's multithreading API

Corentin Jabot corentin.jabot at gmail.com
Wed Feb 20 19:16:45 CET 2013


Hi. I'm the one Olivier mentioned :p

I didn't have time to pursue further the work I started, but I intend
to, someday.

The plan, as suggested by thiago was to have a QThread::run(functor)
method acting exactly like QtConcurrent::run, but using a new QThead.
A similar QThreadPool::run function would call a functor in a thread
allocated in its pool.

Those function return QFuture and do not require event loop so this
silly snippet work:

int main() {
    auto future = QThread::run( []() { qDebug() << "Hello world" ; } );
    future.waitForFinished();
}

My goal was to make it as simple as I could.
Anyway, I don't think we should returns a QThread*. the underlying
implementation does not mater and shouldn't mater.
What would you do with a QThread* you can't do with a QFuture ?
The Thread is started right-away, you can't really interrupt the
function until its done, etc.... but you could delete the thread while
it's running, so yeah, I'd rather not a return a pointer to the
thread.


I find the signature "QThread::run(function)", quite straightforward,
there is no confusion about what it does.
I don't think the fact there is also the "static void run()" method is
confusing, but maybe that's just me.
That said, there is no real reason to put these functions in QThread,
except the name.
These functions could be put elsewhere, I actually started to work
with a bunch of free functions before integrated them to QThread


The implementation use the same sort of generator that QtConcurrent.
Thiago suggested making this feature only compatible C++11, which
would make it easier to maintain. I actually envisaged to send a mail
about that particular issue.
Can c++03 really be dropped for that particular feature ?
Also, I we were to make a c++11 only feature, what would be the
benefits over std::async ?

---

About running QObject* methods on a separate thread, it can become
quite complex.
Which slot is called when the thread start ? Which signal makes the
thread quit ? Should the object be deleted afterwards ? Moved back to
its original thread ?

Considering the number of scenario, I'm not sure we would benefit from
a function - the only factorizable part is

QThread* t = new QThread();
obj->moveToThread(t);
connect(t, SIGNAL(finished()), t, SLOT(deleteLater()));


Maybe we should first agree on how QThread sould work before trying to
add yet-another-way.


Regards,
Corentin


2013/2/20 Sze Howe Koh <szehowe.koh at gmail.com>:
> On 21 February 2013 00:02, Rutledge Shawn <Shawn.Rutledge at digia.com> wrote:
>> On 20 Feb 2013, at 4:57 PM, Olivier Goffart wrote:
>>
>>> On Wednesday 20 February 2013 22:45:21 Sze Howe Koh wrote:
>>>> Hi all,
>>>>
>>>> Some time ago there was some talk about improving Qt's multithreading
>>>> API. I'm summarizing them here to stop them from fading into
>>>> obscurity, and to see if there's any interest in following them up.
>>>>
>>>> Here are the tasks mentioned:
>>>> - Replace/Rewrite QtConcurrent [2]
>>>> - Create/Find a good API to replace QtConcurrent::run() for "one-shot" tasks
>>>> [1] - Find a third-party solution for high-level multithreading [2]
>>>> - Find more uses for QFuture, outside of QtConcurrent [3]
>>>> - Influence C++1y by creating a nice multithreading API [4]
>>>>
>>>> Some suggestions were raised:
>>>> - Put a Qt-ish wrapper around TBB [1]
>>>> - Integrate ThreadWeaver back into Qt? [2]
>>>>
>>>> Separately, someone was experimenting with ways to spawn a QObject in
>>>> a secondary thread, without first constructing it in the current
>>>> thread [5]
>>>>
>>>>
>>>> Do you think any of these avenues are worth pursuing?
>>>>
>>>> I've had a quick look at TBB vs. ThreadWeaver. The latter specializes
>>>> in task-oriented programming, while TBB is a more swiss-army-knife
>>>> toolkit, which includes container-based operations similar to
>>>> QtConcurrent. So, if we're to integrate 3rd-party option into Qt, TBB
>>>> would be more worth it (although it'd involve more work too)
>>>
>>>
>>> Someone has already been working of some feature such as:
>>> static QThread::run(QRunable*)
>>> static QThread::run(Function)
>>> static QThreadPool::run(Function)
>>> https://codereview.qt-project.org/#/t/65/
>>
>> There is also this bug about fixing the examples to show the best practice instead of inheriting from QThread:
>>
>> https://bugreports.qt-project.org/browse/QTBUG-29059
>>
>> It sounds like the preferred way will be something different after those patches.
>
> The Qt Project community is divided on what should be the "preferred
> way". Some are strongly against subclassing QThread altogether, but
> others maintain that subclassing QThread has its valid use cases (see
> the actual changes, and the comments in
> https://codereview.qt-project.org/#change,45271)
>
> The first group doesn't like subclassing QThread, because it mixes
> thread control with threaded code, making it easy for newcomers to
> shoot themselves in the foot. The only way around that, currently, is
> to use a worker QObject all the time, with queued signal-slot
> communication. However, this produces overly-complex code and a big
> runtime overhead if you don't actually need an event loop. This, and
> the fact that subclassing is normal in C++, is the basis of the second
> group's stance. (IIRC, the very frequent foot-shooting led to this
> post: http://blog.qt.digia.com/blog/2010/06/17/youre-doing-it-wrong/,
> which was rebutted recently with
> http://woboq.com/blog/qthread-you-were-not-doing-so-wrong.html)
>
> I was hoping that the new, proposed API can address all concerns.
>
>
> Regards,
> Sze-Howe
>
> P.S. I realize I've made quite sweeping statements about people's
> stances; I sincerely hope I've represented all views accurately
> _______________________________________________
> Development mailing list
> Development at qt-project.org
> http://lists.qt-project.org/mailman/listinfo/development



More information about the Development mailing list