[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