PDA

View Full Version : Multiple threads accessing QList



Vikram.Saralaya
8th January 2016, 17:10
Hello all,

I know that Qt containers (QList in my case) are not thread-safe but they support reentrancy.

I have 3 threads:

DataGenerator thread
UI thread
DataToDisc thread


Their responsibility:

DataGenerator thread appends the generated data to a QList.
UI thread requests the latest data whenever it feels like!
DataToDisc thread reads from the beginning and writes the data to disc. It also removes this item from the list (to avoid large lists over time). This is done by using QList::takeFirst(). It does its job only if there are at least 'n' elements in the list. So I am not accessing the same element from multiple threads.


So my question is: Is this approach wrong? I get occasional crashes with the takeFirst(). Could that be because this function causes a list "reordering" or something thereby causing undefined behavior.

Should I not use QList for this purpose?

Thanks :)

Regards
Vikram

^NyAw^
8th January 2016, 17:22
Hi,

Use a QMutex to prevent the concurrent access to the list.

Vikram.Saralaya
8th January 2016, 17:28
Hi NyAw,


Use a QMutex to prevent the concurrent access to the list.
Thanks for the quick response. Performance is very crucial to me, I can use a Mutex, ReadWriteLock etc. for sure. But the approach I suggested was an attempt to avoid such locking.. any input on why that would/wouldn't work would be much appreciated :)

yeye_olive
8th January 2016, 18:44
QList won't do without a mutex. You need a lock-free queue, but that only works as long as all you do is atomically push and pop elements. You are pretty much doomed if your UI thread can inspect the whole structure; for instance, imagine that it is inspecting an element and suddenly the DataToDisc thread pops and deletes that element...

Vikram.Saralaya
8th January 2016, 22:52
Thanks yeye.. But how can I atomically push and pop elements?

d_stranz
9th January 2016, 16:09
I think yeye_olive is trying to tell you that you can't push and pop atomically using a QList - in a multithreaded app, you need to protect access using a mutex if you want to ensure a writer doesn't corrupt what a reader is looking at.

yeye_olive
10th January 2016, 12:12
Indeed, general-purpose containers such as QList do not atomic push and pop operations. If you want to avoid synchronization with mutexes as much as possible, you need specialized containers; see, for instance, the Boot.Lockfree library.

However, the fact that the UI thread can inspect the whole container means that you will probably need heavy synchronization.

Vikram.Saralaya
11th January 2016, 08:08
Thanks Yeye and d_stranz. Its good to know that its not trivial to atomically push and pop in any of the available qt containers.

Mutex isn't an option to me since it does add a lag to the UI thread.

For anyone interested in how I dealt with this:
I ended up creating a custom circular buffer with QAtomicInteger write pointer. I preallocate memory so my DataToDisc thread now just acts like a reader (without worrying about the growing list). Readers can never read beyond the write pointer and hence no corrupt data will ever be read. Works well!

Regards
Vikram