Solved guidelines for designing an application
-
Hi all -
I'm implementing a small program to communicate with an embedded device. I've begun implementing, and I notice that a lot of the work is being done in a slot, which strikes me as both bad practice and bad design.
Here's what the app needs to do:
- allow the user to select a port
- connect to the port, send a notification request to the device through the port, and wait for a reply.
- parse the reply to determine some information about the device
- use this information to construct further messages to the device
- verify the correct reply
- exit on user command.
This program will never be compute bound (or IO bound, for that matter)...it's going to spend most of its time waiting for input,either from the user or from the device port.
Currently all my work is done in the slot which is called when a readyRead() signal is emitted from the port. Is it better practice to do something like set a flag that main() can see, and exit? Then, main could have a loop in which it checks this flag, and does the necessary processing.I'm looking for any general suggestions on proper application layout for this. Thanks...
-
@mzimmers You can just have helper methods or classes which then do the work when called from the slot. If this work is time consuming you can move it to a second thread. Using a flag like you suggested isn't a clean solution and just moves the work to another place (where it does not belong).
-
I understand that in concept, but in practice, how do I notify a helper object from outside the slot? In my case the slot does #3 and #4 above. I'd like to move that work outside the slot.
-
@mzimmers Why do you want to notify it? You just call it in the slot:
void MainWindow::slot() { do_task_3(); do_task_4(); }
If you use a helper object you can use signals/slots: MainWindow just emits signals in that slot and the helper object(s) connect to them and do what ever they need to do.
-
But that's just moving the work to a subroutine; the work is still being done from the slot, right?
Part of my reason for asking this question is that to me, a slot is like a callback in that you'd want to get out of it as quickly as possible. So...how do I shift the work from the slot to another area?
-
@mzimmers If you want to go out of slot as fast as possible than you need to use a thread to do the actual work.
-
Hi jsulm - I'll look at some of the voidrealms tutorials on Qt threads again.
Isn't is generally a good practice to try to get out of a slot as quickly as possible?
-
@mzimmers Sure, it is. As long as the slot is executing your main thread will be blocked - UI will not react and no other slots will be called.
For simple tasks in another thread you can use http://doc.qt.io/qt-5/qtconcurrent.html#run -
@mzimmers said in guidelines for designing an application:
Isn't is generally a good practice to try to get out of a slot as quickly as possible?
I've heard this for interrupts as long as I'm programming. Fact is, in an interrupt routine do whatever needs to be done, but don't delay unneccessary.
Example: If your interrupt routine read serial port data to a buffer, then just add data to that buffer until the buffer is full or an end-of-line char is received. Then signal the main routine that the buffer can be processed.
Other example: I've build a CAN router that receives data from one CAN port and routes to another one, depending on the message. Here everything is done in the interrupt routine. Reading into a buffer and processing later is no option.
You see, both cases are valid. But Qt's signals/slots are different. If you get a signal, then you are actually in the main. Imagine the slot as a subroutine of main, that is called from Qt's event loop. The interrupt processing has already happened in background, leading to the signal at the next event loop cycle.
Of course you should not do blocking operations in a slot, as you block the event loop. Transfer heavy work into a thread, and let the thread raise a signal when it is ready (which is handled in a slot again).This way you get programs that are very clean, easy to understand, and maintain.
-
Thanks guys...this has been very helpful. I don't think my application calls for threading (just not enough work), but based on what you've said, I've reorganized things so that the serial reader exits quickly, and the bulk of the work is done in a different object. At least this way, the I/O handler's processing is kept to a minimum.