PDA

View Full Version : QList and implicit sharing question



Cruz
17th August 2016, 12:54
Hello world!

I am (still) trying to master the implicit sharing feature of Qt containers and I (still) stumble over an issue occasionally. I am attempting to use a QList across two threads and run into a thread safety issue that is triggered by the QList detaching when it doesn't really need to. Here is a sketch of my setup.




// I have a global state visible everywhere, a blackboard if you will, with a QList inside.
class GlobState
{
QList<ActionObject> list;
}

extern GlobState globState;

// This thread is the main control loop that "does" stuff.
class WorkThread : QThread
{
GlobState oldState;

// The QList is populated in an init() function at the end of construction time and it is never changed again.
void init()
{
globState.list << this;
globState.list << that;
globState.list << and more;
}

// The step() function is called periodically by a timer.
void step()
{
// Here I have to call a non-const method of one of the objects inside the QList.
// I believe this is where the detachment happens.
globState.list[0].doSomething();

// Here I take a copy of the global object. This should increase the reference counter
// of the QList, and that is why the doSomething() above should result in a detach.
oldState = globState;
}
}

// A gui thread is drawing the contents of the QList.
class GuiThread : QThread
{
// Drawing is also periodic, in a separate thread.
// All access to the global list in this thread is const.
void draw()
{
for (int i = 0; i < globState.list.size(); i++) // .size() is const
{
// This is the line where it crashes:
globState.list.at(i).draw(); // .at() is const, .draw() is const
}
}
}


In words, I have a global QList that is accessed by two threads at the same time. The QList is populated before the threads start reading it. The items in the QList are never changed in terms of the number or the position of the items. However, in line 27 in my sketch above, I have to access one of the items in a non-const way and modify the state of this item inside the list. The change is thread safe. Then, I take a copy of the list which should increase the reference counter, which then causes detach()-ment at the next non-const access (Is this correct?). And since the detachment happens sometimes during the time the list is being drawn on the gui by another thread, my program crashes.

So what can I do in this case? I would really like to avoid using a mutex, because there is no good reason to do so. If the QList would not detach, everything should work fine.

Cruz

anda_skoa
17th August 2016, 20:28
I think you could use a list of ActionObject* and at() instead of the index operator.
Or use a std::list that copies when copied.

Cheers,
_