I am using QBuffer in ReadWrite
mode. One worker QThread
pushes data in the buffer and another QThread
reads from it.
Does QBuffer
guarantee thread-safety or do I need to derive from QBuffer
and add mutex stuff?
I am using QBuffer in ReadWrite
mode. One worker QThread
pushes data in the buffer and another QThread
reads from it.
Does QBuffer
guarantee thread-safety or do I need to derive from QBuffer
and add mutex stuff?
To quote Mark Summerfield's book C++ GUI Programming with Qt 4:
Qt's thread-safe classes include QMutex, QMutexLocker, QReadWriteLock, QReadLocker, QWriteLocker, QSemaphore, QThreadStorage, and QWaitCondition. In addition, parts of the QThread API and several other functions are thread-safe, notably QObject::connect(), QObject::disconnect(), QCoreApplication::postEvent(), and QCoreApplication::removePostedEvents().
Qt expects that you will use locking mechanisms around most of it's classes. The docs will say "All functions are thread-safe" if they are, and the individual functions will also specify "is thread-safe".
Many Qt classes are reentrant, but they are not made thread-safe, because making them thread-safe would incur the extra overhead of repeatedly locking and unlocking a QMutex. For example, QString is reentrant but not thread-safe. You can safely access different instances of QString from multiple threads simultaneously, but you can't safely access the same instance of QString from multiple threads simultaneously (unless you protect the accesses yourself with a QMutex).
Some Qt classes and functions are thread-safe. These are mainly the thread-related classes (e.g. QMutex) and fundamental functions (e.g. QCoreApplication::postEvent()).
Because QBuffer
is a direct subclass of QIODevice
I would especially expect it not to be thread-safe, but there are container classes that are thread-safe for read-access, but would require locking for write access:
The container classes are implicitly shared, they are reentrant, and they are optimized for speed, low memory consumption, and minimal inline code expansion, resulting in smaller executables. In addition, they are thread-safe in situations where they are used as read-only containers by all threads used to access them.
QBuffer
isn't the best way to communicate between threads as writing to it makes the buffer grows, but reading from it doesn't delete the data at the beginning.
You could instead use signal/slot with a QByteArray
parameter, use QLocalSocket
or write a thread-safe ring buffer class derived from QIODevice
yourself.
That extends QIODevice, and the documentation there states that all methods on QIODevice are reentrant, but doesn't specify any thread safety on top of that. Given that QBuffer doesn't mention anything more I expect that QBuffer is not thread safe.
The simplest way of communicating between threads in Qt is by posting events to the other thread's event queue. This assumes that the other thread spins an event loop. It only needs to spin it periodically where you'd ordinarily check for new data etc.
As several other posters have pointed out, QBuffer is the wrong tool for the job, regardless of thread safety issues.
Is there an intra-process local pipe in Qt? describes a QIODevice based FIFO queue that would be more appropriate for the intended purpose (though it doesn't include any thread safety mechanism)