Results 1 to 4 of 4

Thread: Qt models and multi-threaded inserts

  1. #1
    Join Date
    Jul 2012
    Posts
    247
    Thanks
    29
    Thanked 15 Times in 14 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Qt models and multi-threaded inserts

    Hi,

    Say I have a model subclassed from QAbstractTableModel, which is shown in standard tablewidget.
    The model models a global datastore in my program, but this store is internally threadsafe, and it's assumed that multiple threads will modify the data in it, which can change the rowCount() in the model.

    I am now wondering how to do this safely. Sure, even in the ideal case, there might be a more or less short period where a view could display outdated data or empty rows or such.
    That's fine, but I want a guarantee it wont lead to corruption or crash.

    It's clear the begin/endResetModel methods in the model cant be called from another thread.
    But then what is the right way to do it?


    1) Even if i lock it somehow, is it sufficient to check the row/index in the data() method in order to avoid oob crashes? It should be, right, since the model abstracts my global store, and no other place accesses my global store.
    The danger is though that Qt internally implicitly assumes or asserts that all QModelIndex it ever encounters are always QModelIndex::row() < MyModel::rowCount(). I see no guarantee this is not the case.

    2) How to communicate the change to the backing store from thread X to the model/view living in the main thread Y.
    I suppose a queued signal-slot connection is the easiest way. That is, introduce a new thread_local notification class that lives on thread X, and connect two of its signals to the begin/endResetModel() slots of the model in thread Y.
    That way the change is communicated reasonably quickly, and because I check the size in data() (after locking the store), the worst thing that can happen is an empty row or outdated data in the view for a moment.
    Problem is that beingResetModel() and endResetModel() will potentially+probably both be processed *after* the modification is already made to the backing store. But that should be ok bc of the first question.

    Right?

    Thanks
    Last edited by tuli; 10th November 2024 at 19:30.

  2. #2
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,252
    Thanks
    304
    Thanked 868 Times in 855 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: Qt models and multi-threaded inserts

    These two statements seem inconsistent to me:

    The model models a global datastore in my program, but this store is internally threadsafe, and it's assumed that multiple threads will modify the data in it
    the model abstracts my global store, and no other place accesses my global store.
    If your global store has only one client (second statement), why do you say multiple threads will modify it (first statement)? Do you mean to say that in your program, your model is the only accessor of the data store, but there could be other programs that are also accessing and possibly modifying it?

    You might have to implement more than just the beginResetModel / endResetModel methods - like those for row insertion and removal - unless you want to completely reload the table view every time the database changes.

    Presumably the QSqlTableModel and QSqlTableView classes have been implemented to handle the scenario you are describing. It might be worthwhile to study that source code for ideas. If your data store is based on an SQL DB, then you might be able to use those classes instead of rolling your own.
    <=== The Great Pumpkin says ===>
    Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.

  3. The following user says thank you to d_stranz for this useful post:

    tuli (11th November 2024)

  4. #3
    Join Date
    Jul 2012
    Posts
    247
    Thanks
    29
    Thanked 15 Times in 14 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Qt models and multi-threaded inserts

    Thanks. I meant from a Qt point of view, the store is accessed by different parts of the program (including external plugins, which it turns out sometimes do so from threads).

    Honestly I was not going to reimplement anything, just calling the existing methods to trigger the data refresh.
    It's true that this would reload the table view, but otherwise I imagine it would not be possible to reliably delete or refresh a specific row via queued connections, give the nature of the inter-thread queuing.
    I will look a at the code of those modes. You can imagine my datastore like a global map protected by a mutex, and modified by different threads.


    I am now thinking: Maybe it's better to instead intercept modifications to the store from non-main threads, and queue those modification into the main thread via a blocking queued signal+slot. That way the model on the mainthread can do the actual del/insert, including emitting proper refresh notices. Store modifications from non-main threads get more expensive, but I expect they are rare anyways. Is it a good idea?

  5. #4
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,252
    Thanks
    304
    Thanked 868 Times in 855 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: Qt models and multi-threaded inserts

    Is it a good idea?
    Yes, it seems like this would be a good way to ensure that your UI would always reflect the current state of the data store if all modifications went through your model. Are your program and the plugins the only way to modify your data store? If yes, then it would simplify things if all modifications could go through your model. Since modifications would be queued, I do not think the state of your data store could get out of sync. You might have to lock reads whenever a write is in progress to ensure that no client got a bad record.
    <=== The Great Pumpkin says ===>
    Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.

Similar Threads

  1. Multi-threaded rendering advice
    By jcox23 in forum Qt Programming
    Replies: 0
    Last Post: 5th November 2012, 12:25
  2. Debugging a multi threaded windows app
    By Cruz in forum Qt Programming
    Replies: 5
    Last Post: 10th April 2012, 13:46
  3. signal not emitting from run() in multi-threaded app
    By naturalpsychic in forum Qt Programming
    Replies: 6
    Last Post: 8th April 2011, 06:28
  4. Multi-threaded GUI possible?
    By nurtsi in forum Qt Programming
    Replies: 12
    Last Post: 26th November 2010, 22:52
  5. Qstring toStdString() and Multi-threaded DLL (/MD)
    By Daxos in forum Qt Programming
    Replies: 14
    Last Post: 15th May 2010, 12:57

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.