Krautkanal.com

Veröffentlicht am 2016-01-13 23:43:18 in /prog/

/prog/ 8292: allgemeiner Qt faden

hoangloi Avatar
hoangloi:#8292

Hallo /inf/-Bernd, kennst du Qt? Dieser Bernd mag es ziemlich, insbesondere ein wirklich gutes simples funktionales GUI ist schnell gebaut damit, auch programmatisch, und die portierbarkeit findet Bernd genial. Aber Bernd ist nicht da um Werbung zu machen.

Was hält Bernd von dem Signal und Slot Konzept?
oder soll ich jetzt KC-Stilecht Signal und Schacht sagen?

Diesem Bernd ist aufgefallen, dass insbesondere bei einfachen Programmen Signal uns Slot sehr effizient und seksi sind. Bei komplexen Programmen aber ziemlich mühsam werden können. Macht Bernd etwas falsch?

Als Beispiel ein TCP-Servierer, wenn Bernd robust kotieren will und alle Fälle abdecken will, d.h. auch jede noch so behinderte Fehlfunktion handeln will, kann das mit Signalen und Slots ziemlicher Krebs werden. Kann es sein, dass es in vielen Fällen mit einfachen Threads oder Runnables und sauberem Locking einiges einfacher ist? Prinzipiell findet Bernd das Konzept von Signalen uns Slots sehr stark. Aber eben als komplexer Fall, ein SSL-Slocket hat unter Qt schon mal so 10 Signale die alle einen Einfluss auf den "State" von dem Socket haben. Prozedural von oben nach unten ist das einiges einfacher zu kotieren. Klar die Statemachine ist auch mit Signalen und Slots relativ einfach, aber zum kotieren und den Kot auch zu lesen ist aus der Sicht von Bernd ziemlich kryptisch.

Hinzu kommt dass der Lifecycle von Objekten ja noch sauber gemacht werden muss, insbesondere eben bei Programmkot der auch einiges an "Durchsatz" hat. Und die Ownership und Threadaffinität kommt auch noch dazu, irgendwie hat Bernd das Gefühl, dass man bei den vielen Optionen und Möglichkeiten viel zu schnell einen Fehler gemacht hat der im "Normalbetrieb" nicht auffält, aber genau dann im falschen Moment explodiert oder der Memory mal über die magischen 4GB donnert....

Nun, was denkt Bernd zu der Problematik? Dieser Bernd programmiert gerne und schon eine Weile multithreaded und hat den Eindruck dass man einen Mittelweg gehen soll und Signale und Slots nur dann anwenden soll wenn es auch seksi und einfach ist, z.B. um das GUI geht.

andrewgurylev Avatar
andrewgurylev:#8306

>>8292

>>> Was hält Bernd von dem Signal und Slot Konzept?

Mir gefallen die neuen C++11-Signal/Slots am besten, klappt auch ohne Meta-Object-Compiler.

QObject::connect(object, &Klasse::method, otherObject, &AndereKlasse::andereMethode);

ah_lice Avatar
ah_lice:#8307

>>8292
> Diesem Bernd ist aufgefallen, dass insbesondere bei einfachen Programmen Signal uns Slot sehr effizient und seksi sind. Bei komplexen Programmen aber ziemlich mühsam werden können. Macht Bernd etwas falsch?
Nein, genau die gleiche Erfahrung habe ich auch gemacht.

> Hinzu kommt dass der Lifecycle von Objekten ja noch sauber gemacht werden muss, insbesondere eben bei Programmkot der auch einiges an "Durchsatz" hat. Und die Ownership und Threadaffinität kommt auch noch dazu, irgendwie hat Bernd das Gefühl, dass man bei den vielen Optionen und Möglichkeiten viel zu schnell einen Fehler gemacht hat der im "Normalbetrieb" nicht auffält, aber genau dann im falschen Moment explodiert oder der Memory mal über die magischen 4GB donnert....
Genau so ist es. Exakt solche Fehler hatte ich, weil sich z.B. Signale zwischen Threads unbegrenzt aufstauen, wenn sie nicht schnell genug abgearbeitet werden. Andere Fehler, die passieren können sind Deadlocks, oder - ganz besonders eklig - Objekte, die Signale erhalten, obwohl sie schon freigegeben wurden. Letzteres ist besonders tückisch, weil es oft gut geht und nur einmal alle Jubeljahre knallt. Und selbst wenn man den Fehler mal erwischt, ist er schwer zu debuggen, weil einem aufgrund des indirekten Aufrufs der Callstack fehlt.

Am Anfang dachte ich: Wow, ein GUI-Framework, das von Haus aus Multithreading unterstützt. Leider hat es sich in der Praxis als absoluter Krebs herausgestellt. Das ganze wird unglaublich frickelig und man ist irgendwann nur noch damit beschäftigt, Workarounds zu finden, damit man das machen kann, was man eigentlich will.

Bin inzwischen überzeugt, dass das ganze Signal-Slot-Konstrukt von Qt von Grund auf der falsche Ansatz ist. Es sollte nur einfache Callbacks geben (also quasi Qt::DirectConnection), der ganze Threading-Kram sollte allein dem Programmierer der Anwendung überlassen werden. Denn er muss sich letztendlich sowieso drum kümmern. Das scheint im ersten Moment mehr Aufwand zu sein, ist aber letztlich viel einfacher. Qt gibt dem Programmierer eine falsche Sicherheit und verleitet zu schlechten Konstruktionen, denen man oft gar nicht ansieht, dass sie Fehler enthalten.

adriancogliano Avatar
adriancogliano:#8308

>>8306
> C++11-Signal/Slots
> ohne Metacompiler
oh Hunt, ja das ist schick!

>>8307
> Bin inzwischen überzeugt, dass das ganze Signal-Slot-Konstrukt von Qt von Grund auf der falsche Ansatz ist
Brufaust!

> schwer zu debuggen
OP hat schon seit ca 5 Jahren keinen debugger genutzt, ist vermutlich auch der Grund warum Bernd Qt aushält...

Na ja, Bernd wird vermutlich trotzdem Qt verwenden für seine Projekte, die Platformunabhängigkeit ist leider zu geil (Linux, Win, Mac, iOS, Android alles in einem Guss, das gibts sonst nirgends nativ).Vielleicht wird Bernd einfach etwas mehr mit "klassichen" Threads und simplem Locking, Queues und so arbeiten. Alles andere ist ja sonst de facto ein Active-Object-System :)

okcoker Avatar
okcoker:#8328

> C++11-Signal/Slots
> ohne Metacompiler

Meh, kann mensch auch ohne Qt: https://woboq.com/blog/reflection-in-cpp-and-qt-moc.html

Apropro ohne Qt: Gibt es gute Alternativen?

mrxloka Avatar
mrxloka:#8329

>>8328
Leider nicht mit dem selben Funktionsumfang und Qualitätsmanagement.

craighenneberry Avatar
craighenneberry:#8330

>>8307

Ich bin noch extremer: ich lehne Multithreading weitestgehend ab.

Grafische Oberflaechen bekommt man am besten korrekt gezeichnet, indem man dem System mitteilt, dass bestimmte Teile veraltet sind und aktualisiert werden muessen, und anschliessend auf eine Benachrichtigung wartet, dass sich ueberhaupt jemand dafuer interessiert.

Das loest gleich mehrere Probleme auf einmal: verdeckte Fenster nehmen keine weitere Rechenzeit weg und Aktualisierungen stauen sich nirgendwo auf.

Ich wage auch zu behaupten, dass 90% der Programme da draussen mit einem Thread komplett klarkommen, weil sie ohnehin die meiste Zeit auf das naechste Ereignis warten.

thehacker Avatar
thehacker:#8332

>>8328
> Apropro ohne Qt: Gibt es gute Alternativen?
glaube kaum, also mals ernsthaft, so eine riesige Codebase wie Qt muss man erst mal kotiernen. Von RS-232, via SSL, über GUI, Fensterchen, Systemtrayicons, Threads, Drag'und'Drop nach Android, iOS und zurück nach Windows 10 und Linux.... Also da braucht man ein grosses, kluges und motiviertes Team mit einem guten Übervater, der sehr viel Zeit und Geld hat.
Ausserdem, die sind ja schon seit gefühlten 20 Jahren dran. Das macht niemand so schnell nach.

>>8330
> Grafische Oberflaechen bekommt man am besten korrekt gezeichnet, indem man dem System mitteilt, dass bestimmte Teile veraltet sind und aktualisiert werden muessen, und anschliessend auf eine Benachrichtigung wartet, dass sich ueberhaupt jemand dafuer interessiert.
Wuut? Das wird seit 9000 Jahren so gemacht.

> Ich wage auch zu behaupten, dass 90% der Programme da draussen mit einem Thread komplett klarkommen
> weil sie ohnehin die meiste Zeit auf das naechste Ereignis warten
> ich lehne Multithreading weitestgehend ab.
> Ich bin noch extremer
Offensichtlich.
Und offensichtlich kotierst du keinen Kot der auch von anderen Personen als dir genutzt wird.

alek_djuric Avatar
alek_djuric:#8336

>>8330
Wie bringt man dort animierte UIs rein?

johnriordan Avatar
johnriordan:#8350

>>8328

>> Apropro ohne Qt: Gibt es gute Alternativen?
Es gibt Alternativen, ob sie gut sind ist die andere Frage:
http://www.wxwidgets.org/
- Audacity läuft damit
- wxPython ist ein populäres Bindung zur Programmiersprache Python
- Der VLC Player wurde anfangs damit entwickelt (ist inzwischen bei Qt)
spätestens mit der Neulizenzierung von Qt unter der LGPLv3 ist wxWidgets wohl uninteressant

http://www.fltk.org/
- nur GUI Toolkit

http://www.gtk.org/
- Mit der Umstellung von Version 2 auf Version 3 versuchen viele auf Qt zu wechseln: Wireshark, LXDE, ...

souuf Avatar
souuf:#8354

>>8350
>Ob sie gut sind ist eine andere Frage...
Jenes.

>inzu4 eigenes Widgetset mit SDL schreiben
SDL unterstützt scheinbar keine Interruptloops mehr, SDL_WaitEvent pollt scheinbar nun intern.

n_tassone Avatar
n_tassone:#8509

Ein Fehler ist oft dass man falsch kapselt. Wenn ein Objekt einem anderen mittels 50 Signalen mit je 5 Parametern seinen Zustand mitteilen soll, ist das Design schon mal etwas schief. Da wären mehrere Lösungen möglich:
1) RegisterMetaType verwenden um einen komplexen Zustandsdeskriptor aus 50 Parametern mit einem einzigen Signal zu verschicken
2) Der Deskriptor könnte auch seinen eigenen Zustand auswerten, also schon mal einfache logische Verknüpfungen der internen Parameter machen
3) Zustandsautomat in Beobachter-Klasse kapseln, ändert seinen Zustand ausgrund ankommender komplexer Signale (evtl aus mehreren Quellen) und verschickt selber Signale um den Zustand eines oder mehrerer Zielobjekte zu ändern.

Quelle->signal(Zustandsdeskriptor)->BeobachterObjekt->signal(VerarbeiteterZustand)->Zielobjekt

danro Avatar
danro:#8510

>>8307
Deine Probleme sind allerdings auch schon etwas gehobenes Level. Das Problem ist doch eigentlich nur dass Qt den Eindruck erweckt, Nebenläufigkeit im Griff zu haben. Das ist aber bei jeder effizienten API immer die Entwickleraufgabe.
* Was threads angeht: die sollen möglichst nicht am Frontend benutzt werden, weil die nativen APIs also X11 oder Quartz sowas garnicht können. Threads kannst du aber gut brauchen, wenn du z.B. im Hintergrund eine komplexe Grafik als QImage zeichnest, ohne die Responsiveness zu ruinieren. Aber das Setzen muss immer schön aus dem Hauptthread geschehen. Was die meisten auch nicht wissen: QPixmap NIEMALS für threaded painting verwenden, das gibt debugger Probleme ohnegleichen und bizarre Abstürze. Nur QImage.
* Signalstau: Empfängerobjekt im Hauptthread steckt die Daten aus den empfangenen Signalen in eine begrenzte queue, der Thread selber sagt demselben wann er fertig ist und wieder Zeit hat. Signale sind also vom Thread entkoppelt, gehen halt verloren wenn die Empfängerqueue überläuft.
* Was gelöschte Signalempfänger angeht: object->deleteLater() anstatt delete object; sorgt dafür dass das Ding erst nach dem nächsten Lauf der Eventqueue verschwindet. Queued connections können dann kein Problem machen.

ovall Avatar
ovall:#8511

>>8330
> Ich wage auch zu behaupten, dass 90% der Programme da draussen mit einem Thread komplett klarkommen
90% der Programme da draussen verursachen auch keine massiven Probleme wenn sie blockieren weil sie von Sonderschülern geschrieben wurden.

seanwashington Avatar
seanwashington:#8513

>>8510
> * Signalstau: Empfängerobjekt im Hauptthread steckt die Daten aus den empfangenen Signalen in eine begrenzte queue, der Thread selber sagt demselben wann er fertig ist und wieder Zeit hat. Signale sind also vom Thread entkoppelt, gehen halt verloren wenn die Empfängerqueue überläuft.
So ähnlich haben wir es dann auch gelöst, das ist aber eine echte Murks-Frickel-Lösung. Und auch keine 100%ige, dafür aber unnötig kompliziert und ineffizient.

tweet_john Avatar
tweet_john:#8555

Ich bin eigentlich mit folgendem Vorgehen immer gut gefahren:
- Threads nur wenn absolut nötig
- Nachrichtenaustausch über queued connections statt shared data
- keine komplizierten Verflechtungen zwischen den Zuständen von mehreren Threads

Die I/O-Klassen sind meiner Meinung nach auch nicht so gut, und ich habe mich schon sehr intensiv mit denen beschäftigt. Der Typ, der dafur zuständig ist, ist sehr intelligent und weiß sehr viel, aber sein Kot ist schlecht organisiert. Alles ein großer Sack Variablen mit Methoden, die nach Belieben an diesen herumspielen.

Neuste Fäden in diesem Brett: