[SOLVED] Qt philosophy? ("+" for "JKSH", "lpapad" and "sierdzio")
-
[quote]"By definition, threads run in parallel if you have multiple cores. If you only have a single core (or if you have more threads than cores), the system will use time-slicing to give the illusion of parallelism. This applies to all threads, not just Qt threads."
Not the case with .NET.[/quote]It's also the case with .NET. From "Threads and Threading, .NET Framework 4.5":http://msdn.microsoft.com/en-us/library/6kac2kdh.aspx:
"Because each time slice is small, multiple threads appear to be executing at the same time, even if there is only one processor. This is actually the case on multiprocessor systems, where the executable threads are distributed among the available processors."
[quote]=> Thread are asynchronous, but not necessarily parallel (thread re-use).
A separate new threadpool can be used, though.
Looks a lot like .NET threading.[/quote]I don't quite follow your argument. Can you please explain how reusability and parallelism are mutually exclusive?Remember:
- The degree of parallelism you can achieve is limited by the number of physical cores you have
- In a typical non-microcontroller OS today, no program gets truly exclusive access to any core, because the processes that the OS spawns at startup already outnumber the cores in a typical machine.
[quote]Where did it come that in O-O circles the"only right way" to do threading is to make the threads program-internal processes (all with their own resources). "The object lives in a thread..." = objects are resources of threads.[/quote]A more accurate comparison would be: "The object lives in this thread" = "The object runs its slots in this thread".
Aside from a thread's dedicated stack, the OS has no concept of "this resource belongs to this thread". Any such philosophical association is created only to help developers visualize and manage the system.
[quote][quote]Qt is a cross-platform framework, so just use Qt’s built-in classes. They abstract away the underlying HW implementation.[/quote]And if there is no such class... (a more exotic device)[/quote]Ah, you meant external hardware. Sorry, I thought you meant hardware on your PC.
Anyway, it depends on your communications protocol. If you can, just use QTcpSocket, QUdpSocket or QSerialPort to send/receive commands. If you can't, write your own driver as you would with any other embedded system.
You can use the QIODevice interface with your driver to get automatic signal emission when data is read/written, or you can use a plain old C++ class that sets flags to communicate with your engine. I would generally go for the first option.
[quote]I was asking if there are "common conventions".
You can write all C-code in one file and one function very much in a Basic-like way - the language doesn't stop you - but don't expect your code to be accepted anywhere.[/quote]The documentation has many compilable examples, some of which span many files. Study them to get an feel of the conventions in use.
-
[quote]I'd think that the threading and signal/slot system have an intended role, and they are supposed to affect the program structure, but how?
...
I'm very new to Qt, but not to programming or C++ or OSs.
(More than 20 years of experience about embedded SW.)[/quote]I think I better understand your questions and where you're coming from now.Qt is an event-driven framework. Qt encourages developers to write asynchronous code that react to to signals. Signals are simply function declarations; slots are simply functions that run whenever a connected signal is emitted. The meta-object compiler adds a definition to the signal at compile-time, to hook it into the event system.
The signal-slot mechanism is an extension of traditional event systems. The differences are:
- Simpler interfaces, more flexible, more extensible:
** In Java, the sender needs to create special Event objects and the receiver needs to implement the relevant Listener interface.
** In Qt, a signal can be connected to any function with a parameter list that matches the parameter list of the signals. It is trivial to create a new high-level signal: Just create a new function prototype with a descriptive name. No need to create a whole new class. - Easy to use in a multithreaded environment:
** Java needs all events to be dispatched from one thread.
** In Qt, all threads can emit signals which can be received by any other thread. In fact, this is the preferred way of inter-thread communications, as mentioned in one of the links I sent you.
Having said that, Qt reduces the need for developers to create threads.
- Traditionally, you'd implement timers and networking by getting a thread to poll and sleep periodically.
- Qt exposes an asynchronous API to accomplish this, so you can (and often should) implement everything in the main thread.
** To be precise, Qt's networking classes use threads behind the scenes, but this is abstracted away from developers
For the purposes of discussing GUI implementations below, forget about threads and think of asynchronous execution only.
[quote]About GUI interaction with a model, I mean like in Java, you are supposed to use notification events, and with C#/WPF you use bindings.
You CAN do it other ways, but those are generally encouraged.[/quote]Generally, the GUI emits signals to announce that the user has done something (clicked a button, selected a menu item). These signals are connected to the engine's slots, which run when the GUI emits a signal. The same thing happens the other way -- the engine emits signals to announce that processing has finished, announce that a network packet has arrived, provide the GUI with updated data, etc. The GUI slots respond to those signals and update themselves.C++ GUIs use signals+slots only.
QML GUIs use a combination of signals+slots and bindings.
Signals+slots aren't restricted to GUI interaction; you can also do event-driven data processing.
- Simpler interfaces, more flexible, more extensible:
-
"Ah, you meant external hardware. Sorry, I thought you meant hardware on your PC."
Oh, on my PC I could have a data board os DSP board or...But now you are speaking a language I understand. ;-)
When it comes to .NET, I once made a trial - 3 threads generating output strings: thread identification + number with 1 second between outputs.
First the first thread run to the end, then the second started and run to the end, and then the 3rd. Not really parallel even with dual core processor.Now if the threads should have exchanged the data...
Also threads shouldn't depend on HW.
-
[quote author="turboscrew" date="1381388366"]"Ah, you meant external hardware. Sorry, I thought you meant hardware on your PC."
Oh, on my PC I could have a data board os DSP board or...But now you are speaking a language I understand. ;-)[/quote]Too many languages out there; I don't always pick the best one off the bat ;)
You'll probably find that desktop programmers think very differently from embedded system programmers. I'm guessing that's why you started this discussion.
[quote]When it comes to .NET, I once made a trial - 3 threads generating output strings: thread identification + number with 1 second between outputs.
First the first thread run to the end, then the second started and run to the end, and then the 3rd. Not really parallel even with dual core processor.[/quote]Hmm... Can't comment much without seeing your implementation or knowing what else your system was running at the time.In any case, the OS is the one that decides when each thread runs, and for how long before the thread has to yield.
[quote]Now if the threads should have exchanged the data...[/quote]Then you must "synchronize them":http://doc-snapshot.qt-project.org/qt5-stable/threads-synchronizing.html. The page even links to examples that show you how to do that. MSDN would probably have similar examples.
[quote]Also threads shouldn't depend on HW.[/quote]How do you propose making a single-core CPU and a dual-core CPU handle 2 threads the same way?
May I ask what kinds of OS'es you've been working with?
-
"In any case, the OS is the one that decides when each thread runs,"
No, it's the thread scheduling policy within framework or language runtime.
(threadpool handling)."Then you must synchronize them"
Queues are used for asynchronous communications - no synchronization needed. Also synchronization is not always needed with global "atomic" data that has one writer and many readers, although synchronization is recommended even then."How do you propose making a single-core CPU and a dual-core CPU handle 2 threads the same way?"
If threading is time-slicing that utilizes n cores.
Very common way. Threads usually work even concurrently with single core."May I ask what kinds of OS’es you’ve been working with?"
Windows (NT, CE, 2000)
Linux
ChorusOS
OS9
OSE for DSP
OSEck
And a couple of proprietary OSes.
No OS (bare iron)Those are the OSes that I have written kernel level code for.
There are then some OSes that I have used, but not written kernel level code for.Also, not OSes, but environments: Ada and Occam.
I'm also quite familiar also with pthreads.
-
[quote author="turboscrew" date="1381467762"]"How do you propose making a single-core CPU and a dual-core CPU handle 2 threads the same way?"
If threading is time-slicing that utilizes n cores.
Very common way. Threads usually work even concurrently with single core.[/quote]You know, that is how I, and the .NET documentation, have been describing thread management all along.[quote author="turboscrew" date="1381467762"]"In any case, the OS is the one that decides when each thread runs,"
No, it's the thread scheduling policy within framework or language runtime.
(threadpool handling).[/quote]A framework defers to the OS for thread scheduling. Linux, for example, only supports the PTHREAD_SCOPE_SYSTEM contention scope, not PTHREAD_SCOPE_PROCESS. Thus, the OS allocates time slices to all threads from all processes as one big group.All threadpool threads in Qt and .NET run in parallel. However, Qt and .NET do NOT use thread pools exclusively for multithreading.
In your .NET test, you did not say:
- Whether you used the thread pool or standalone threads.
- How you configured your threads.
- Where your CLR was hosted -- Some hosts can limit your threadpool size.
If you had used a threadpool size of 1 to run your test, that would explain your results.
[quote author="turboscrew" date="1381467762"]"May I ask what kinds of OS’es you’ve been working with?"
Windows (NT, CE, 2000)
Linux
ChorusOS
OS9
OSE for DSP
OSEck
And a couple of proprietary OSes.
No OS (bare iron)...
I'm also quite familiar also with pthreads.[/quote]The Linux implementation of Qt threads uses pthreads. If you're interested in the implementation details: https://qt.gitorious.org/qt/qtbase/source/src/corelib/thread/qthread_unix.cpp
On Windows, Qt uses Win32 threads. The other OS'es you listed aren't supported.
[quote author="turboscrew" date="1381467762"]"Then you must synchronize them"
Queues are used for asynchronous communications - no synchronization needed. Also synchronization is not always needed with global "atomic" data that has one writer and many readers, although synchronization is recommended even then.[/quote]If you had opened the link I gave you, you would have found a detailed explanation on how to use signals and slots pass messages between threads through event queues, and why that approach is recommended approach over thread locking (traditional synchronization).Speaking of which, you started this discussion looking for insight into the underlying mechanisms that drive Qt applications. Multithreading aside, have you found answers to your questions yet?
-
Threadpool threads run in parallel, but .NET threading by default lets the framework to decide how many threads to use and which threads to reuse.
I don't think (my example) that time slice could have been 10 seconds.You can use standalone threads with C#/WPF too, but not directly. At least you need to define the job "long lasting".
I have tried to use the signals/slots, and I think that's the way it should work in O-O environment. Nice!
bq. Speaking of which, you started this discussion looking for insight into the underlying mechanisms that drive Qt applications. Multithreading aside, have you found answers to your questions yet?
Some of it. The picture is forming...
I'll check the Linux implementation as soon as I have little time. Thanks for the link!
-
More concrete questions:
I'm writing a simple external device commander that "discusses" with the computer via serial port. There are two kinds of commands: simple one line commands and a bit more complex multiblock commands. A block is some hundreds of bytes long. Simple command is just a couple of tens of bytes long.
Is it good idea to have mainwindow to handle the UI, simple commander, block commanderand a device specific serial handler (using the QSerialPort)? Later on, the UI will be dropped and the rest is to be moved into a "subsystem" of a bigger whole.
The mainwindow has slots of all "command sending" widgets (mostly buttons), and when a command is sent, it gets that data from other fields (command parameters) and sends the bunch to the appropriate commander, that handle the command and "code" them using the device specific serial handler.
The mainwindow has "command signals" and "response slots" and so do the command handlers and the device specific serial handler.
The mainwindow ties the "command signals" and "response slots" together, except that the device specific serial handler connects its "command signals" and "response slots" with the QSerialPort stuff.
Is that an OK structure? Am I overusing/underusing signals/slots?
How about handling ACK-messages? Those can come for both simple and multiblock commands. Is it better to use a flag for routing the ACK to the appropriate commander, or is re-connecting signals/slots between the device specific serial handler and the appropriate commander a preferred way?
-
It sounds like your main window is being used for rapid prototyping, so having it handle the commanders/serial handler is fine. It's faster to manipulate code this way.
If it were a permanent of the system though, I'd separate the UI from the commanders/handler, and have them communicate via signals+slots without being made aware of each others' existence.
[quote]The mainwindow has slots of all “command sending” widgets (mostly buttons), and when a command is sent, it gets that data from other fields (command parameters) and sends the bunch to the appropriate commander[/quote]Just to check that I've understood your description correctly. Did you mean this sequence?:
Your window's slot reads the input data fields
It packages the data
It emits the data in a signal
The signal parameters "enter" the relevant commander slot
If so, then you already have good separation between your UI and your workers. That's a good use of signals+slots.
[quote]How about handling ACK-messages? Those can come for both simple and multiblock commands. Is it better to use a flag for routing the ACK to the appropriate commander, or is re-connecting signals/slots between the device specific serial handler and the appropriate commander a preferred way?[/quote]I would have one class monitor the serial port for incoming messages. When it receives one, it decodes it, and...
- Either call the relevant handler function directly, or
- Send the decoded message the relevant handler class through a signal
-
bq. Just to check that I’ve understood your description correctly. Did you mean this sequence?:
Your window’s slot reads the input data fields
It packages the data
It emits the data in a signal
The signal parameters “enter” the relevant commander slotYes.
Also the clicks and selections (combobox) come to the main window slots as signals, but the textbox stuff is just read from the ui.
I wonder if that's overdoing/underdoing it?bq. I would have one class monitor the serial port for incoming messages. When it receives one, it decodes it, and…
Either call the relevant handler function directly, or
Send the decoded message the relevant handler class through a signalThat spells:
"use a flag for routing the ACK to the appropriate commander"Lots of thanks!
I guess when I get further I'll stuff my question heap into a new thread.How do I mark the problem solved, and is there a way to give points to answerers?
-
[quote author="turboscrew" date="1381936192"]Also the clicks and selections (combobox) come to the main window slots as signals, but the textbox stuff is just read from the ui.
I wonder if that's overdoing/underdoing it?[/quote]A bit hard to tell from descriptions alone. Can you share your main window code?[quote]Lots of thanks!
I guess when I get further I'll stuff my question heap into a new thread.How do I mark the problem solved, and is there a way to give points to answerers?[/quote]You're welcome :)
The common way is to edit your original post and add "[SOLVED]" to your title. This forum doesn't support identification of answers or up/downrating of individual posts/posters (yet?), unfortunately.