Search code examples
c++multithreadingqtqt-signalsqbytearray

QByteArray emited and connected by value through QueuedConnection and appended to race condition?


I have a signal newData(int type, QByteArray data) connected as a queuedConnection to slotNewData(int type, QByteArray data) and then I emit two data callbacks as shown here

emit newData(OEI_DataParserV2_base::OEI_CBT_DOUBLE, dp_v2_databuff_);
uint32_t sec;
uint32_t usec;
dataParserV2->getDataTimestamp(sec,usec);
dp_v2_databuff_.append(reinterpret_cast<const char*>(&usec), sizeof(usec));
dp_v2_databuff_.append(reinterpret_cast<const char*>(&sec), sizeof(sec));
emit newData(OEI_DataParserV2_base::OEI_CBT_TIMESTAMP_DOUBLE, dp_v2_databuff_);

I am expecting my slot to receive the data without the appended timestamp and then the data with the appended timestamp. However I am seeing sometimes the data coming back with type OEI_CBT_DOUBLE with the extra appended timestamp. I see that the QByteArray is implicitly shared but that the data should be copied-on-write. The Qt Documentation specifically says

Note that atomic reference counting does not guarantee thread-safety. Proper locking should be used when sharing an instance of an implicitly shared class between threads. This is the same requirement placed on all reentrant classes, shared or not. Atomic reference counting does, however, guarantee that a thread working on its own, local instance of an implicitly shared class is safe. We recommend using signals and slots to pass data between threads, as this can be done without the need for any explicit locking.

Should the QByteArray::append not create a deep copy of my dp_v2_databuff_? Should I be passing my QByteArrays through queuedConnections by const ref or by value?


Solution

  • So the bug that brought this discussion up has been solved now. The QByteArray is appended to in every iteration of this code and therefore grows larger and larger past timestamps stuck to the end of it.