I have 3 objects(inherited from QObject
) that each contain a separate std::list
. Each object gets created in the main gui thread (with no parent) and then is pushed to it's own thread (using Qt's QObject::moveToThread()
).
Each thread is hooked up to a gui and messages are sent between the different threads with data. Each thread is to essentially handle it's own list. For example:
Obj 1 : Consumer of data. It pop's the front off of its list(if data is present) to use. It also has a SLOT available so that other threads can push data to it. No other object can access this list directly only the the original QObject class.
Obj 2 : Producer of data. It pushes data to its list. It has SLOTS available for others to 'ping' it for data which will in turn emit a SIGNAL popping data from its list. No other object can access this list directly.
Obj 3: Produces data for obj 1 and consumes data from obj 2. It has it's own internal data structures that keep track 开发者_StackOverflow中文版of the data sent to obj 1 and the data coming from obj 2. It finally will push both data sets to some QwtPlots
after it does some analysis.
Obj's 1 and 2 are real-time critial and use QueryPerformanceCounter style 'timing' which will essentially suck down a CPU each while they're running. They run QCoreApplication::processEvents()
every loop to handle the events that come down through.
Is this an okay way to handle cross-thread data sharing? If it isn't, where are the holes and how would you correct them? I understand this will create a lot of 'copies' of data flying around, but memory bloat isn't a concern at this point.
thanks in advance :)
It's hard to say exactly whether it's thread-safe or not without all the implementation details as there are a lot of things that can go wrong when using threads.
Obj 1 : Consumer of data. It pop's the front off of its list(if data is present) to use. It also has a SLOT available so that other threads can push data to it. No other object can access this list directly only the the original QObject class.
If this slot is connected to signals in other threads (such as Obj 3) using queued or auto connection type, then the Obj 1 is probably safe. If the slot is called directly from other threads, then it obviously isn't thread safe unless you explicitly synchronize everything.
Obj 2 : Producer of data. It pushes data to its list. It has SLOTS available for others to 'ping' it for data which will in turn emit a SIGNAL popping data from its list. No other object can access this list directly.
You don't mention how "pinging" is implemented or which threads call those slots. If other threads call them directly and if pinging involves accessing the internal std::list, then you're in trouble. If those slots are only called via queued or auto connections (to some signal in Obj 3, for example), then it's fine. If those slots are thread safe (for example, they only put a "ping" message into some sort of internal synchronized message queue), then it's fine too. The latter way looks like custom reimplementation of the queued connection mechanism, though.
Overall, this whole thing looks too dangerous to me as slots can be called from anywhere by mistake. I'd try to avoid this kind of thing by putting some safety checks there, like this:
void Obj2::ping() {
if (QThread::currentThread() != this->thread()) {
// not sure how efficient it is
QMetaObject::invoke(this, "ping", Qt::QueuedConnection);
return;
}
// thread unsafe code goes here
}
精彩评论