[Threads & Signals] emitting an object vs using a pointer to a queue
Im developing an application which will be responsible to interact with an hardware platform and as such I need to send and receive some data packets. I also must ensure the data flow control, ie, one packet is sent only when the the ACK of the previous one is received.
Im implementing this with two threads (main GUI thread and a separate one - the "comm thread"). An object living in the main GUI thread generates the packets and the comm thread sends them. Since the comm thread can send only one packet at a time (wainting for the ACK), somekind of queue should exists to store "pending packets".
I have two possible implementations on my mind (both using signals/slots to communicate between threads):
Packets to be sent are stored in a QQueue (in the object that runs on the GUI thread). When creating the comm thread I get the pointer to that queue and the thread continuously polls it. This is a typical producer/consumer scenario where I will need to use a QMutex (or QReadWaitLock, or QWaitCondition?). I didn't test this situation, will it work? What do you think?
Passing the packet itself through a signal (emited by the GUI thread and received by the comm thread). No need for synchronisation since a Qt::QueuedConnection already provides it aswell as a queue (ie, any resources being shared, signals are queued). However, is it efficient to pass objects through signals? (which involves copy I think)
What do you think?
Huh, a tough topic where everybody is likely to have a different opinion.
I would opt strongly for number 2 :-D The more stateless a program is, the better (usually. There are exceptions everywhere), as it implies good separation of data and logic, UI and logic, and in general does a lot of good to the code (easier testing, for example). I suppose the packets you send are text-based? Then you can simply pass const QString & references: it is cheap and fast. In general, don't be too worried about performance, especially if you are passing const objects and/ or using Implicit Sharing. Even a read-only pointer would do just fine, I guess. And if the object needs to be copied: well, no problem, really. Copying data is ultra-fast. In my opinion, there is really a lot of things that are better than mutexes :P
I'm with sierdzio on that one, solution number 2 should give you enough performance and a lock free implementation is nicer when possible.