[Qt-interest] AmIRight: Can't Have Model and View on different Threads?
Stephen Kelly
steveire at gmail.com
Sun Aug 16 13:21:18 CEST 2009
Arnold Krille wrote:
> Hi,
>
> On Thursday 13 August 2009 08:07:01 Stephen Kelly wrote:
>> Arnold Krille wrote:
>> > On Friday 07 August 2009 07:36:30 Hostile Fork wrote:
>> >> The short version is that I don't think it's feasible for a Model to
>> >> be modified on a non-GUI thread...regardless of whether the model's
>> >> data has been protected with read/write locks. If what I'm gathering
>> >> is correct, then Qt should probably have an assert that a model and
>> >> its view have the same thread affinity (it doesn't seem to do that
>> >> now)
>> > I would find such an assert quite disturbing. Because here it works
>> > well to have models and views in different threads.
>> Can you say more about this? How does it work with QueuedConnections?
>> What happens if a row gets added then removed, and because of the queue,
>> the view only gets to process the added signal after the row has been
>> removed?
>
> While the slot of a QueuedConnection is not called right away, it is just
> converted to an event sent to the receivers event-loop. But there is no
> reordering of the event-loop. So there is no way the added-slot is called
> after the removed-slot in your example.
I guess you misunderstood what I wrote. I didn't mean anything gets
reordered. But because the signals get queued, the begin*Rows and end*Rows
signals are all emitted after the model has changed its internal data
structure, rather than before and after.
I just committed a unit test for this:
http://websvn.kde.org/?view=rev&revision=1011890
Note that at the end of ModelInsertAndRemoveQueuedCommand::doCommand, the
internal structure of the model has changed, but no signals have been
emitted yet.
When ModelQueuedConnectionsTest::rowsInserted tries to process the
rowsInserted signal, the rows that were inserted have already been removed.
If you swap the comments in ModelInsertAndRemoveQueuedCommand::doCommand and
comment out the event loop in the test, you will see that the test "fails"
because the just-inserted rows are valid.
As QAbstractItemView uses AutoConnections, the signals will be queued if
they are in another thread. So, AFAIU, the model and view must be in the
same thread if things are not to break. It's not impossible that a model
would try to insert and remove rows in quick succession.
If you haven't hit a situation where a signal queue like that doesn't form,
I'd say you just got lucky.
>
> And that actually works nice. My models normally reset themselfes
> completely because when the number of rows changes, the bin-width (its
> models used for statistics) changes which invalids any data. So its faster
> to remove everything and call reset to signal the views to get everything
> new... And my models cache updates, with >5000 changed values a second,
> you don't want to emit dataChanged() to often.
Models shouldn't reset themselves completely when the number of rows
changes. Do you get a lot of messages something like "Internal
representation of model corrupted. Resetting."?
>
> You can find the ((L)GPLv3) code at http://positron.physik.uni-
> halle.de/EPOS/Software/ which is the last stable release, but the
> model/view stuff hasn't changed in the last months...
>
> I am also open for tests showing where my models and views are wrong. :-)
> The ModelTest from QtLabs is kind of limited (but nevertheless showed me
> some errors).
Yes, it's a good idea to also write your own unit tests. ModelTest is good
for smoke testing.
All the best,
Steve.
>
> Have fun,
>
> Arnold
More information about the Qt-interest-old
mailing list