The equivalent to a BlockingQueue is inherent in each QObject
. It's not explicitly stated in the Qt documentation for QObject (like it should be!), but there is an event queue effectively for every QObject out there. You can use the static QCoreApplication::postEvent
method to post events to any QObject, from any thread -- as long as you have a pointer to a QObject, you can post events to it.
Signal-slot connections of the Qt::QueuedConnection
type use that same event queue to post internal QMetaCallEvent
events. Those events are picked up by QObject::event()
and result in calls to relevant slots. When control goes back to the thread's event loop, the latter looks at the event queue and passes events to the QObject::event()
methods.
Those built-in event queues are very useful because they inherently let you serialize the access to a QObject, so you don't have to add extra synchronization primitives, and you avoid setting yourself up for deadlocks. Using ad-hoc synchronization leads to trouble, even Java got things wrong by design, unfortunately. See Herb Sutter's excellent exposes on this topic: The Many Faces of a Deadlock and Avoid Calling Unknown Code While Inside a Critical Section. He has plenty of other publications on this and related topics, it's a true treasure trove of knowledge. He also explains how to design run-to-completion, short-and-sweet asynchronous applications for good performance.
If you base your design on QObjects and connections between them using signals-slots and event posting, you're ready to move any of those QObjects to a dedicated QThread should your profiling/benchmarking indicate a need of doing so. Anything that derives from a QWidget cannot leave the GUI thread, though.