amiga-news ENGLISH VERSION
.
Links| Forum| Kommentare| News melden
.
Chat| Umfragen| Newsticker| Archiv
.

amiga-news.de Forum > Programmierung > RastPort und Multithreading [ - Suche - Neue Beiträge - Registrieren - Login - ]

-1- 2 [ - Beitrag schreiben - ]

26.01.2010, 14:40 Uhr

Der_Wanderer
Posts: 1229
Nutzer
Hallo!

Ich arbeite an einem GUI Toolkit, das mutlithreaded arbeitet, damit visuelles Feedback unabhängig von der eigentlichen Applikation möglich ist.
Da beide, der GUI Thread und der Applikations Thread auf den RastPort des gleichen Fensters zugreifen, muss ein synchronisations Mechanismus her, da es sonst logischerweise Chaos gibt.

Wie würdet ihr das machen?

Im Moment scheint mir LockLayer()/UnlockLayer() am geeignetsten, obwohl es mir nicht nur um den Layer geht, sondern auch um den RastPort Zustandspeicher, sprich A/B Pen, Fonts etc.
Da LockLayer wie eine Semaphore arbeitet, bietet sich das an, um den ganzen RastPort zu schützen.
Eine eigene Semaphore will ich nicht unbedingt mitführen, das würde die API um einen Parameter mehr aufblähen.

Allerdings kann ich mich noch dunkel daran erinnern, dass unter OS4 ein Fenster RastPort nicht zwingend einen Layer hat, sondern der entsprechende Eintrag in der RastPort Struktur NULL sein kann. In dem Fall kann man logischerweise auch nichts locken. Ist das tatsächlich so?


--
HD-Rec, Sweeper, Samplemanager, ArTKanoid, Monkeyscript, Toadies, AsteroidsTR, TuiTED, PosTED, TKPlayer, AudioConverter, ScreenCam, PerlinFX, MapEdit, AB3 Includes und viele mehr...
Homepage: http://www.hd-rec.de



[ Dieser Beitrag wurde von Der_Wanderer am 26.01.2010 um 14:42 Uhr geändert. ]

[ - Antworten - Zitieren - Direktlink - ]

26.01.2010, 16:01 Uhr

thomas
Posts: 7717
Nutzer

Ich würde das Fenster in einem eigenen Task öffnen und alle Zeichenoperationen in diesem Task ausführen. Wenn ein Objekt meint, sein Erscheinungsbild aktualisieren zu müssen, schickt es eine Message an den Task und der führt die Arbeit aus. Dadurch hast du automatisch eine Serialisierung und das Fenster arbeitet vollkommen unabhängig vom Hauptprogramm, antwortet also auch auf Benutzereingaben, wenn gerade eine längere Berechnung läuft.

Gruß Thomas

--
Email: thomas-rapp@web.de
Home: thomas-rapp.homepage.t-online.de/

[ - Antworten - Zitieren - Direktlink - ]

26.01.2010, 16:03 Uhr

Holger
Posts: 8116
Nutzer
Zitat:
Original von Der_Wanderer:
Da beide, der GUI Thread und der Applikations Thread auf den RastPort des gleichen Fensters zugreifen, muss ein synchronisations Mechanismus her, da es sonst logischerweise Chaos gibt.

Wie würdet ihr das machen?

Nicht den gleichen RastPort verwenden.

Da das sowieso nur funktionieren kann, wenn die Zeichenoperationen wirklich nebenläufig sind, sollte man auch zulassen, dass beide Threads ungehindert parallel laufen können und sich nicht gegenseitig blockieren. Da der RastPort nunmal einen Status beinhaltet (das ist seine primäre Aufgabe), muss dafür jeder Thread seinen eigenen RastPort benutzen.

--
Good coders do not comment. What was hard to write should be hard to read too.

[ - Antworten - Zitieren - Direktlink - ]

26.01.2010, 16:26 Uhr

Der_Wanderer
Posts: 1229
Nutzer
@Thomas, Holger

Diese beiden Antworten habe ich erwartet.

@Thomas:
Das geht nicht, weil nicht alle Widgets unter der Verwaltung des GUI Toolkits stehen. Z.b. Custom View Widgets werden vom Benutzer innerhalb des Applikations Kontextes gezeichnet.

Der Applikations Programmierer muss sich, damit das geordnet abläuft, den RastPort erst reservieren:

code:
RastPort *rp = ntui_ObtainRastPort(tuiObject);
if (rp) {

  ... tue hier etwas mit dem RastPort

  ntui_ReleaseRastPort(rp);
}


So, wie das auf anderen Betriebssystemen Gang und Gebe ist.

@Holger
Das kann man mit eigenen RastPorts tun, aber wie geht das bei einem Fenster?

Dazu müsste ich den RastPort des Fensters clonen und aktuell halten. Der Layer kann sich ja bei jedem Fenster Resizing ändern.
Ich sehe nicht, wie das vernünftig möglich sein sollte. Intuition hat eigene RastPorts für die Fenster Dekoration, aber Intuition kann das natürlich alles kontrollieren.

Den RastPort müsste sich die Applikation trotzdem noch holen/freigeben, damit ich z.B. nicht mittem im Zeichnen das Fenster unter des Füssen wegschliesse, z.b. wenn eine ScreenNotify Message kommt.

--
HD-Rec, Sweeper, Samplemanager, ArTKanoid, Monkeyscript, Toadies, AsteroidsTR, TuiTED, PosTED, TKPlayer, AudioConverter, ScreenCam, PerlinFX, MapEdit, AB3 Includes und viele mehr...
Homepage: http://www.hd-rec.de


[ - Antworten - Zitieren - Direktlink - ]

26.01.2010, 16:36 Uhr

Holger
Posts: 8116
Nutzer
Zitat:
Original von Der_Wanderer:
Dazu müsste ich den RastPort des Fensters clonen und aktuell halten.

Was verstehst Du unter "aktuell halten"?
Zitat:
Der Layer kann sich ja bei jedem Fenster Resizing ändern.
?
Der RastPort besitzt einen Zeiger auf den Layer und dieser Zeiger bleibt immer der gleiche.
Zitat:
Den RastPort müsste sich die Applikation trotzdem noch holen/freigeben, damit ich z.B. nicht mittem im Zeichnen das Fenster unter des Füssen wegschliesse, z.b. wenn eine ScreenNotify Message kommt.
Ja, wenn Du die Fenster schließt und nicht die Anwendung, dann müssen Du und die Anwendung wohl miteinander reden. Da führt dann kein Weg vorbei.

--
Good coders do not comment. What was hard to write should be hard to read too.

[ - Antworten - Zitieren - Direktlink - ]

26.01.2010, 16:50 Uhr

Der_Wanderer
Posts: 1229
Nutzer
Zitat:
Original von Holger:
Zitat:
Original von Der_Wanderer:
Dazu müsste ich den RastPort des Fensters clonen und aktuell halten.

Was verstehst Du unter "aktuell halten"?
Wenn sich was im Fenster ändert, z.b. der Layer, die Bitmap (?) oder sonstwas. Eigentlich bei jedem Pointer den man dupliziert läuft man Gefahr, dass er ungültig wird.

Zitat:
Zitat:
Der Layer kann sich ja bei jedem Fenster Resizing ändern.
?
Der RastPort besitzt einen Zeiger auf den Layer und dieser Zeiger bleibt immer der gleiche.

Ist das so? OS4 hat manchmal NULL im Layer stehen, oder?
Und was passiert, wenn ich beim Zeichen die Clip Region verändere?

Zitat:
Zitat:
Den RastPort müsste sich die Applikation trotzdem noch holen/freigeben, damit ich z.B. nicht mittem im Zeichnen das Fenster unter des Füssen wegschliesse, z.b. wenn eine ScreenNotify Message kommt.
Ja, wenn Du die Fenster schließt und nicht die Anwendung, dann müssen Du und die Anwendung wohl miteinander reden. Da führt dann kein Weg vorbei.
Auch wenn die Applikation das Fenster schliesst, müssten wir miteinander kommunizieren.

Und im ganzen betrachtet, würde sich doch der Layer als Semaphore eigenen, oder nicht?
Allerdings ist das sehr heikel, falls man einen Intuition Aufruf machen muss. Deshalb wäre mir eine andere Lösung lieber.

Ich könnte noch dem Fenster eine Semaphore anhängen. Aber bessere wäre es an den RastPort, aber der ist kein "tuiObject" was ich einfach erweitern kann.




--
HD-Rec, Sweeper, Samplemanager, ArTKanoid, Monkeyscript, Toadies, AsteroidsTR, TuiTED, PosTED, TKPlayer, AudioConverter, ScreenCam, PerlinFX, MapEdit, AB3 Includes und viele mehr...
Homepage: http://www.hd-rec.de



[ Dieser Beitrag wurde von Der_Wanderer am 26.01.2010 um 16:51 Uhr geändert. ]

[ - Antworten - Zitieren - Direktlink - ]

26.01.2010, 17:09 Uhr

thomas
Posts: 7717
Nutzer
Zitat:
Original von Der_Wanderer:
Der Applikations Programmierer muss sich, damit das geordnet abläuft, den RastPort erst reservieren:

code:
RastPort *rp = ntui_ObtainRastPort(tuiObject);
if (rp) {

  ... tue hier etwas mit dem RastPort

  ntui_ReleaseRastPort(rp);
}



Dann verpaß doch dem tuiObject einen Semaphore und laß dir bei ReleaseRastPort das tuiObject übergeben und nicht den RastPort.


Zitat:
So, wie das auf anderen Betriebssystemen Gang und Gebe ist.

Wenn du das Betriebssystem benutzen würdest, hättest du ObtainGIRPort und ReleaseGIRPort zur Verfügung.

Gruß Thomas

--
Email: thomas-rapp@web.de
Home: thomas-rapp.homepage.t-online.de/

[ - Antworten - Zitieren - Direktlink - ]

26.01.2010, 17:40 Uhr

Der_Wanderer
Posts: 1229
Nutzer
> Dann verpaß doch dem tuiObject einen Semaphore und laß dir bei
> ReleaseRastPort das tuiObject übergeben und nicht den RastPort.
Es kann aber auch zwei tuiObject geben, die sich einen RastPort teilen.
Ich müsste den Lock hochpropagieren bis zum tuiObject, das den RastPort hält.

Der Sinn des Toolkits ist (unter anderem), eben nicht das OS Gadgets Gemurkse zu nutzen. Ansonsten käme das GIRPort doch recht nahe an das, was ich suche.


--
HD-Rec, Sweeper, Samplemanager, ArTKanoid, Monkeyscript, Toadies, AsteroidsTR, TuiTED, PosTED, TKPlayer, AudioConverter, ScreenCam, PerlinFX, MapEdit, AB3 Includes und viele mehr...
Homepage: http://www.hd-rec.de


[ - Antworten - Zitieren - Direktlink - ]

26.01.2010, 19:47 Uhr

Holger
Posts: 8116
Nutzer
Zitat:
Original von Der_Wanderer:
Wenn sich was im Fenster ändert, z.b. der Layer, die Bitmap (?) oder sonstwas. Eigentlich bei jedem Pointer den man dupliziert läuft man Gefahr, dass er ungültig wird.

Du scheinst hier einem großen Denkfehler aufgesessen zu sein: wenn Du in einem Thread einen RastPort benutzt und in einem anderen Thread gleichzeitig etwas tust, das RastPort, Layer oder BitMap ungültig werden lässt, ist es vollkommen egal, ob es der originale Window-RastPort oder eine Kopie davon ist: es knallt so oder so.
Zitat:
Ist das so? OS4 hat manchmal NULL im Layer stehen, oder?
Die einzige Operation, die unter AOS3.x dazu führen kann, dass der Layer verschwindet, ist das Schließen des Fensters. AOS4 hat gar keine andere Wahl, als zu allen unter AOS3.x vorhandenen Funktionen kompatibel zu sein.

Also möglicherweise musst Du bei neuen Funktionen, wie HideWindow() aufpassen, aber das müsste ja in der Dokumentation dieser Funktionen stehen.
Zitat:
Und was passiert, wenn ich beim Zeichen die Clip Region verändere?
Mach's lieber nicht...

Zitat:
Auch wenn die Applikation das Fenster schliesst, müssten wir miteinander kommunizieren.
Ich bin davon ausgegangen, dass die Anwendung das Toolkit anweist, ein Fenster zu schließen. Danach wissen beide, dass das Fenster zu ist.
Zitat:
Ich könnte noch dem Fenster eine Semaphore anhängen. Aber bessere wäre es an den RastPort, aber der ist kein "tuiObject" was ich einfach erweitern kann.
Und das Fenster ist ein tuiObject?

--
Good coders do not comment. What was hard to write should be hard to read too.

[ - Antworten - Zitieren - Direktlink - ]

26.01.2010, 22:12 Uhr

Der_Wanderer
Posts: 1229
Nutzer
Alle Objekte sind tuiObjekte in NTUI, selsbt die Engine.
Und eben auch Fenster. Sie haben eine Größe, Position, Border und Kinder/Eltern tuiObjekte, eine Layout, EventHandle, Get/SetAttr, MinSize, Draw Methode wie alle anderen tuiObjekte auch.

Das AmigaOS Fenster ist nur dazu da, um es anzuzeigen und wird in einem Feld des tuiWindow Structs referenziert. Ein tuiWindow muss nicht sichtbar sein um zu existieren.


Bild: http://www.hd-rec.de/pics/tuiconcept.png

> Ich bin davon ausgegangen, dass die Anwendung das Toolkit anweist, ein Fenster zu schließen.
Das muss nicht sein. Das Toolkit kann Fenster auch auf eigeninitiative Schliessen, z.B. wenn der Screenmode Prefs sich ändert oder die Preferences von NTUI. Die Applikation muss davon nichts mitbekommen, aber wenn sie auf einem Fenster rumwerkelt, dann muss das Fenster/RastPort solange blockiert sein.

--
HD-Rec, Sweeper, Samplemanager, ArTKanoid, Monkeyscript, Toadies, AsteroidsTR, TuiTED, PosTED, TKPlayer, AudioConverter, ScreenCam, PerlinFX, MapEdit, AB3 Includes und viele mehr...
Homepage: http://www.hd-rec.de



[ Dieser Beitrag wurde von Der_Wanderer am 26.01.2010 um 22:15 Uhr geändert. ]

[ Dieser Beitrag wurde von Der_Wanderer am 26.01.2010 um 22:19 Uhr geändert. ]

[ Dieser Beitrag wurde von Der_Wanderer am 26.01.2010 um 22:22 Uhr geändert. ]

[ - Antworten - Zitieren - Direktlink - ]

26.01.2010, 22:53 Uhr

Holger
Posts: 8116
Nutzer
Zitat:
Original von Der_Wanderer:
Das Toolkit kann Fenster auch auf eigeninitiative Schliessen, z.B. wenn der Screenmode Prefs sich ändert oder die Preferences von NTUI. Die Applikation muss davon nichts mitbekommen, aber wenn sie auf einem Fenster rumwerkelt, dann muss das Fenster/RastPort solange blockiert sein.

Ein solches gleichzeitiges Werkeln sollte schon konzeptionell ausgeschlossen werden. Vielleicht solltest Du Dir noch mal anschauen, wie das im AmigaOS funktioniert, bevor Du versuchst, es besser zu machen.

--
Good coders do not comment. What was hard to write should be hard to read too.

[ - Antworten - Zitieren - Direktlink - ]

27.01.2010, 11:08 Uhr

Der_Wanderer
Posts: 1229
Nutzer
> Ein solches gleichzeitiges Werkeln sollte schon konzeptionell ausgeschlossen werden.
Entweder durch Semaphoren oder kein Multithreading. Wie sollte man das sonst bewerkstelligen? Die Applikation wird immer auf dem Fenster was tun wollen, z.B. bei Custom Views wie bei HD-Rec oder ArtEffekt.

--
HD-Rec, Sweeper, Samplemanager, ArTKanoid, Monkeyscript, Toadies, AsteroidsTR, TuiTED, PosTED, TKPlayer, AudioConverter, ScreenCam, PerlinFX, MapEdit, AB3 Includes und viele mehr...
Homepage: http://www.hd-rec.de


[ - Antworten - Zitieren - Direktlink - ]

27.01.2010, 15:28 Uhr

Holger
Posts: 8116
Nutzer
Zitat:
Original von Der_Wanderer:
Entweder durch Semaphoren oder kein Multithreading.

Oder durch Messages (siehe Beitrag von thomas) oder in dem nur einer das Recht besitzt zu zeichnen. Das heißt nicht, dass nicht andere Dinge parallel laufen können.

Wenn ich mir allerdings Deine Objektgraphen da oben anschaue und die Unbeschwertheit mit der Du meinst, es sei einzig der RastPort, der einer Synchronisation bedarf, würde ich Dir "kein Multithreading" empfehlen.

--
Good coders do not comment. What was hard to write should be hard to read too.

[ - Antworten - Zitieren - Direktlink - ]

27.01.2010, 15:45 Uhr

Der_Wanderer
Posts: 1229
Nutzer
Sehr geehrter Herr Holger,

Wenn ich mir die Unbeschwertheit deiner Signatur so anschaue, würde ich mir selbst empfehlen von dir keinen Rat anzunehmen.
Die klugen Köpfe in der Amiga Szene sind aber leider sehr rar geworden, und ich schätze dich als einer der wenigen verbleibenden AmigaOS API Großmeister. Deshalb reiße ich mich jetzt ein wenig zusammen und werde nicht ausfallend.

Was stört dich an dem Objektgraphen von oben?

Andere Teile (z.B. der Applikations-übergreifende Bitmap Cache) sind bereits mit Semaphoren synchronisiert. Mine Frage ging um den RastPort, ob es da eben AmigaOS seitig Möglichkeiten gibt, da ein RastPort kein von mir erzeugtes Objekt ist dem ich so einfach eine Semaphore verpassen könnte. Und ich wollte auch das tuiWindow Objekt nicht gerne missbrauchen, denn ein RastPort muss auch nicht zwingend von einem Fenster kommen.

--
HD-Rec, Sweeper, Samplemanager, ArTKanoid, Monkeyscript, Toadies, AsteroidsTR, TuiTED, PosTED, TKPlayer, AudioConverter, ScreenCam, PerlinFX, MapEdit, AB3 Includes und viele mehr...
Homepage: http://www.hd-rec.de



[ Dieser Beitrag wurde von Der_Wanderer am 27.01.2010 um 15:46 Uhr geändert. ]

[ - Antworten - Zitieren - Direktlink - ]

27.01.2010, 16:08 Uhr

Der_Wanderer
Posts: 1229
Nutzer
Aber um nochmal drauf zurückzukommen:

Die meisten Dinge werden per Messages oder eben im Toolkit Kontext erledigt. Das geht beim Zeichnen aber nicht wirklich, wenn eine Applikation etwas "eigenes" darstellen will. Da kommt man nicht drumherum, der Applikation einen RastPort zu überreichen, auf dem sie dann rum-malen darf.


--
HD-Rec, Sweeper, Samplemanager, ArTKanoid, Monkeyscript, Toadies, AsteroidsTR, TuiTED, PosTED, TKPlayer, AudioConverter, ScreenCam, PerlinFX, MapEdit, AB3 Includes und viele mehr...
Homepage: http://www.hd-rec.de


[ - Antworten - Zitieren - Direktlink - ]

27.01.2010, 16:20 Uhr

akl
Posts: 265
Nutzer
@Der_Wanderer:

Was spricht gegen

- ObtainWindow(ntui_context, &window)
- ObtainRastPort(ntui_context, window, &rastport)
- werkel()
- 2x Release...


[ - Antworten - Zitieren - Direktlink - ]

27.01.2010, 16:47 Uhr

Der_Wanderer
Posts: 1229
Nutzer
Also erstmal sollte der App Programmierer nicht davon ausgehen, dass er ein bestimmtes Fenster haben möchte. Was er möchte ist der RastPort, in den er zeichnen muss wenn er sein Custom View Widget füllen will. Der kann auch NULL sein, wenn z.B. der Custom View gar nicht sichtbar ist.
Ob das nun von einem Fenster kommt oder sonst woher sollte - und muss - ihm egal sein, sonst kann man z.b. auch kein (für ihn) transparentes Double Buffering machen. (d.h. die Funktion stellt ihm nicht den Fenster RastPort, sondern einen Off-screen-RastPort, nach dessen Release wird das ganze im Fenster sichtbar. <= wäre denkbar, ist momentan noch nicht geplant).

Also idealerweise würde es so aussehen:

code:
RastPort *rp = ntui_ObtainRastPort(tuiObject *myCustomViewTuiObject);
if (rp) {

  werkel();

  ntui_ReleaseRastPort(rp);
}


Leider weiss der arme RastPort ja nichts von NTUI. Und ich kann ihm das auch nicht beibringen, da AmigaOS Struct.

Also müsste ich es wohl so machen:

code:
tuiObject *myCustomView = ...
RastPort *rp = ntui_ObtainRastPort(myCustomView);
if (rp) {

  werkel();

  ntui_ReleaseRastPort(myCustomView, rp);
}


Ist ein Parameter mehr, wo man was verbocken kann. Aber evtl. noch akzeptabel. (ich versuche eben die API sehr effizient zu machen).

--
HD-Rec, Sweeper, Samplemanager, ArTKanoid, Monkeyscript, Toadies, AsteroidsTR, TuiTED, PosTED, TKPlayer, AudioConverter, ScreenCam, PerlinFX, MapEdit, AB3 Includes und viele mehr...
Homepage: http://www.hd-rec.de



[ Dieser Beitrag wurde von Der_Wanderer am 27.01.2010 um 16:49 Uhr geändert. ]

[ - Antworten - Zitieren - Direktlink - ]

27.01.2010, 18:10 Uhr

akl
Posts: 265
Nutzer
@Der_Wanderer:
Das ist der Punkt. Du musst einen Kontext definieren und durch die API durchschleifen.

[ - Antworten - Zitieren - Direktlink - ]

27.01.2010, 18:15 Uhr

akl
Posts: 265
Nutzer
@Der_Wanderer:
Wenn's im Einzelfall eventuell nur darum geht, den Aufrufer zu identifizieren, wäre auch denkbar, jedem Task seine eigene Library-Base zu geben... hier aber eher nicht.

[ - Antworten - Zitieren - Direktlink - ]

27.01.2010, 18:25 Uhr

Der_Wanderer
Posts: 1229
Nutzer
Nein, den Aufrufer muss ich nicht identifizieren.
Jedes Applikation erzeugt ja eine (oder mehrere) tuiEngines (siehe Objektgraph).
Und jedes tuiObject kennt auch seine tuiEngine. (die tuiEngine ist nichts anderes als das oberste (Wurzel) tuiObject von der Unterklasse tuiEngine im Baum).

--
HD-Rec, Sweeper, Samplemanager, ArTKanoid, Monkeyscript, Toadies, AsteroidsTR, TuiTED, PosTED, TKPlayer, AudioConverter, ScreenCam, PerlinFX, MapEdit, AB3 Includes und viele mehr...
Homepage: http://www.hd-rec.de


[ - Antworten - Zitieren - Direktlink - ]

27.01.2010, 19:00 Uhr

akl
Posts: 265
Nutzer
@Der_Wanderer:

Sorry, nochmal einen Schritt zurück: was ist eigentlich mit rp->RP_User? Habe gerade kein Autodoc zur Hand, aber... es sieht stark nach einem benutzerdefinierbaren Pointer aus.

Was den Aufrufer angeht, kann man daraus ggf. mit etwas Aufwand auch den Kontext ableiten, solange nicht derselbe Rastport nicht nur in mehreren Threads sondern auch in mehreren Engines verwendet wirds. Aber wie gesagt... hier eher nicht.

[ Dieser Beitrag wurde von akl am 27.01.2010 um 19:01 Uhr geändert. ]

[ - Antworten - Zitieren - Direktlink - ]

28.01.2010, 00:47 Uhr

whose
Posts: 2156
Nutzer
@Der_Wanderer:

Vorweg: Ich bitte schon mal um Verzeihung, falls ich das Problem nicht verstanden haben sollte. Ich hoffe dennoch, die eine oder andere Anregung geben zu können.

Irgendwie erschließt sich mir Dein Problem nicht wirklich. Wenn ich das Ganze richtig verstehe geht es Dir darum, einer Anwendung die Möglichkeit zu geben, in entweder ein von Deiner GUI-Engine bereitgestelltes "Widget" oder völlig "frei" nach Belieben in ein Fenster hineinzumalen. Dabei stößt Du, aufgrund der Mutli-Threading-Geschichte, auf das Problem, daß ein RastPort schlecht von theoretisch beliebig vielen Threads gleichzeitig "mißbraucht" werden kann.

Mir stellen sich da die Fragen: Ist das wirklich so? Und wenn ja, wo liegt nun wirklich das Problem?

Gehen wir mal von dem Fall aus, daß in einem Fenster, welches bereits ein paar "Standard-Widgets" enthält, ein "Plätzchen" zum freien Bemalen durch die Applikation freigehalten wird. Nun sind die "Widgets", wenn ich das Ganze recht verstanden habe, "Threads", die unabhängig von der Applikation Operationen auf den Rastport ausführen können. Ist das korrekt?

Wenn dem so ist, wie hast Du es dann bei den "Widgets" gelöst, daß diese nicht nach Gusto auf dem Rastport manipulieren? Und wo liegt dann das Problem, die Applikation quasi zu verpflichten, eigene Aktionen auf den Rastport "anzumelden"? ObtainGIRPort() & Co. wären dann doch bereits ausreichend, wenn Deine "Widgets" sich ebenfalls an dieses Protokoll halten.

Noch simpler ist die Sache, wenn der Applikation nur Manipulation auf ein von Dir so bezeichnetes "Custom View Widget" erlaubt ist. In diesem Fall kannst Du sogar intern eine erweiterte Rastport-Struktur verwenden, nach "außen" aber nur den Standard-Teil sichtbar machen, bzw. nur so viel, wie die Applikation wissen muß. Dieser Teil läßt sich sogar so weit anpassen, daß es für die Applikation so aussieht, als käme diese Struktur von einer OS-Funktion und wäre somit auch für OS-Funktionen ohne weiteres verwendbar. Und natürlich hast Du dann auch die Möglichkeit, diesen "Spezial-Rastport" GUI-intern zu "locken", bis die Applikation Vollzug der eigenen Manipulation meldet.

In wie weit das allerdings "visuelles Feedback unabhängig von der Anwendung" ermöglichen soll, liegt irgendwie außerhalb meines Horizonts. Wirklich unabhängig wäre das visuelle Feedback ja nur dann, wenn alle Elemente der Visualisierung theoretisch gleichzeitig aktiv sein dürften, was sie bei einem Lock, egal wie dieser letzten Endes realisiert wird, niemals können.

Andererseits ist ein GUI schon dann von der Applikation unabhängig, wenn es sich, unter Einhaltung der vom OS gesetzten Grenzen, "selbst", also ohne direkte und nötige Manipulation durch die Applikation, aktualisieren kann.

Deswegen habe ich auch das Problem vieler Entwickler mit BOOPSI nie verstanden. Es gibt halt Situationen, in denen die "Unabhängigkeit" eines GUI-Systems an Grenzen stößt und das GUI "Starthilfe" von der Applikation benötigt. Ok, manches hätte man bei BOOPSI durchaus eleganter lösen können, aber es spricht eigentlich nichts dagegen, diese Fehler zu korrigieren, wenn sie einen stören...
--
---

:boing: µA1 PPC 750GX-800
:boing: A4000 PPC 604e-233

[ - Antworten - Zitieren - Direktlink - ]

28.01.2010, 11:08 Uhr

Holger
Posts: 8116
Nutzer
Zitat:
Original von Der_Wanderer:
Wenn ich mir die Unbeschwertheit deiner Signatur so anschaue, würde ich mir selbst empfehlen von dir keinen Rat anzunehmen.

Die Signatur ist ja auch nicht als Antwort auf eine Frage gedacht. Und nein, ich werde auch in Zukunft keine Ironie-Tags hinschreiben.
Zitat:
Was stört dich an dem Objektgraphen von oben?
An dem Objektgraphen stört mich gar nichts, der sieht wie überall aus. Und wie bei allen anderen Toolkits, die man so kennt, ergibt sich dort eben keine Möglichkeit, threadsafe ohne locking zu arbeiten.

Da jede Zeichenoperation vom Zustand des Objektgraphen abhängt, muss also der zugehörige Thread bereits einen entsprechenden Lock für den Objektgraphen besitzen, womit die Einführung eines weiteren Locks für den RastPort irgendwo zwischen überflüssig und hochgradig deadlock-gefährded liegt.

Da es somit ohnehin keinerlei Parallelität gibt, lautet die Antwort also: single-threaded ist die einfachste Möglichkeit dasselbe Ergebnis zu erlangen.
Zitat:
Original von Der_Wanderer:
Und jedes tuiObject kennt auch seine tuiEngine. (die tuiEngine ist nichts anderes als das oberste (Wurzel) tuiObject von der Unterklasse tuiEngine im Baum).

Naja, an anderer Stelle hast Du gesagt, dass Du die API möglichst effizient machen möchtest. Ein Objektgraph, bei dem jedes Objekt erneut seinen eigenen Kontext ermitteln und womöglich auch noch locken muss, ist nicht effizient--und auch nicht einfach zu programmieren.

Eine Zeichenfunktion, die einen Kontext übergeben bekommt, der bereits alles nötige enthält und auch die nötigen locks besitzt, erspart einen Menge Arbeit. Schließlich kann man dann auch einen kompletten Objektgraphen mit nur einer Lock-Operation zeichnen.

Außerdem ist es wesentlich praktischer, wenn der Aufrufer für Koordinatentransformation und Clipping zuständig ist. Dann ist es nämlich auch kinderleicht, z.B. eine ScollPane zu implementieren, die einen beliebigen Inhalt haben kann, der nur ausschnittsweise zu sehen ist.
Zitat:
Original von Der_Wanderer:
Die meisten Dinge werden per Messages oder eben im Toolkit Kontext erledigt. Das geht beim Zeichnen aber nicht wirklich, wenn eine Applikation etwas "eigenes" darstellen will.

Ich kann Deine Schlussfolgerungen nicht nachvollziehen. Bei anderen Toolkits geht das doch auch. Bei BOOPSI wird anwendungsspezifischer Code im GUI-Kontext aufgerufen, bei MUI wird der andere Weg gewählt und alle GUI-Operationen im Anwendungskontext ausgeführt.
Zitat:
Da kommt man nicht drumherum, der Applikation einen RastPort zu überreichen, auf dem sie dann rum-malen darf.
Kommt man nicht drumherum?
Wo ist denn der Unterschied für die Anwendung, ob sie nun
Draw(rastPort, 5, 10);
oder
ntuiDraw(ntuGfxContext, 5, 10);
oder
DrawLine(ntuGfxContext, 5, 10);
aufruft?

--
Good coders do not comment. What was hard to write should be hard to read too.

[ - Antworten - Zitieren - Direktlink - ]

28.01.2010, 13:48 Uhr

Der_Wanderer
Posts: 1229
Nutzer
Also eigentlich habe ich hier ja nur mal ins Blaue gefragt, da man hier oft sehr interessante Hinweise bekommt.

Ich muss aber ein wenig mehr erläutern:

Das Konzept meines GUI Toolkit sieht eher aus wie MUI, und ist schon recht weit durchdacht und auch bereits zu grossen Teilen implementiert.

Sämtliche Kommunikation mit dem Benutzer läuft über die ntui.library.
Alle Events, seien es IDCMP, AREXX, ScreenNotify, App oder etwas, was in Zukunft noch kommt, bekommt man von EINER Warteschlange, die man mit EINER Funktion abfrägt. Die Messages gehören nicht notwendigerweise zu einem "physikalischen" Fenster. Eine Message trägt die ID der Aktion, nicht die ID des auslösenden GUI Elements. (soweit dies Möglich ist)
Aus Applikations-Sicht ist es mir ja auch völlig wurscht, wenn man ein Fenster schließen möchte, ob der User nun auf das CloseGadget gedrückt hat, ESC gedrückt oder einen "Exit" Knopf betätigt hat. Wenn man das doch unterschieden möchte, trifft man die Unterscheidung beim Designen der GUI, nicht beim Implementieren der App.

Die Abkopplung von AmigaOS Fenstern ist wichtig, damit tuiObjecte z.B. an/abgedockt werden können und vieles mehr. Ein tuiObjekt muss auch nicht immer sichtbar sein, trotzdem kann man es manipulieren, mit Daten füllen usw. Aus Sicht der Applikation ist das völlig egal.

Die Messages, die man verarbeitet, sind auch nicht mehr Amiga spezifisch, d.h. wenn man mit NTUI arbeitet tauchen (normalerweise) keinerlei AmigaOS Defines oder Funktionen mehr auf. Das ist wichtig für eine evtl. Portierbarkeit. Kleine Ausnahme ist hier das zeichnen eigener Custom Views, da man hier sowieso Amiga Spezifischen Code erwarten muss. Wobei das Konzept des RastPort natürlich auf so gut wie allen Betriebssystemen verwendet wird, unter Windows ist das der DrawContext.
Da gebe ich allerdings wirklich den RastPort raus, und nicht einen abstrahierten "DrawContext", damit man alle AmigaOS und 3rd Party Funktionen nutzen kann, die ja normalerweise auf einem AmigaOS RastPort arbeiten.

Momentan läuft NTUI synchron (wie MUI), d.h. jedesmal, wenn die Applikation ntui_GetEvent() aufruft, um an neue Events zu kommen, werden alle Operationen durchgeführt wie GUI Refresh, abholen aller Arten von Messages.
Das funktioniert auch gut so, solange die Applikation nicht blockiert ist. Das ist ja der häufigste Kritikpunkt an MUI. Deshalb möchte ich, zumindest in der Version 2.0, das Abholen der Messages und das optische Reagieren der GUI in einem separaten Thread machen. Für den App Programmierer ist das natürlich alles transparent. Synchron/Asynchron kann man dann evtl. in den Preferences von NTUI wählen.

Auch da ist eigentlich alles vorbereitet, nur mache ich mir Gedanken über den RastPort, der eben auch von der Applikation selbst bearbeitet werden können muss.
NTUI soll so einfach wie nur irgendwie möglich für den App Programmierer sein. Also deutlich einfacher als BOOPSI oder MUI.
Mein Ziel ist es, dass der App Programmierer sich auf die App konzentriert, während es bei den meisten Amiga Toolkits schon fast die Hauptaufgabe der App ist, sich mit der GUI auseinanderzusetzen.

Und da benötige ich einen geeigneten Mechanismus, wie der Thread von NTUI nicht mit dem Thread der Applikation in die Quere kommt.

Ich denke die Lösung mit "ntui_ObtainRastPort" ist wohl die beste.
D.h. der App Programmierer muss sich den RastPort jedesmal erfragen. So kann ich seine Zeichenoperationen auch beliebig umleiten, z.B. für DoubleBuffering.
Das sollte den App Programmierer ja nicht weiter stören. Irgendwoher muss er sich den RP ja sowieso besorgen.

Und noch für alle, die evtl. den Kopf schütteln und sich denken "noch so ein GUI Ding":
Ich denke dass NTUI tatsächlich einige Vorteile bietet, für den User und für den App Programmierer, die die anderen Toolkits nicht haben.
Aber ob es jemand benutzen wird ausser mir, muss man erst noch sehen...

--
HD-Rec, Sweeper, Samplemanager, ArTKanoid, Monkeyscript, Toadies, AsteroidsTR, TuiTED, PosTED, TKPlayer, AudioConverter, ScreenCam, PerlinFX, MapEdit, AB3 Includes und viele mehr...
Homepage: http://www.hd-rec.de



[ Dieser Beitrag wurde von Der_Wanderer am 28.01.2010 um 13:57 Uhr geändert. ]

[ Dieser Beitrag wurde von Der_Wanderer am 28.01.2010 um 14:00 Uhr geändert. ]

[ - Antworten - Zitieren - Direktlink - ]

28.01.2010, 14:03 Uhr

thomas
Posts: 7717
Nutzer

Läuft das Aktualisieren der Custom-Views vollkommen unabhängig von der GUI ? D.h. kann die Anwendung egal in welchem Stadium sie gerade ist einfach mal ObtainRastPort aufrufen, alles neu zeichnen und ReleaseRastport, fertig ? Oder wird die Aktualisierung von der GUI angestoßen, z.B. beim Ändern der Fenstergröße oder beim "Abdocken" von Elementen ?

In letzterem Fall könntest du bereits vor dem Aufruf der User-Routine die betroffenen Grafikelemente per Semaphore blockieren, ohne daß die Anwendung etwas davon mitbekommt.

Wenn die Anwendung selbst bestimmen kann, wann sie ihre Elemente neu zeichnet, dann bleibt dir nichts anderes übrig, als beim ObtainRastPort einen Semaphore zu blockieren. Der muß ja nicht unbedingt mit dem RastPort verknüpft sein. Du holst den Rastport ja irgendwo her. Da kannst du ja auch den Semaphore unterbringen.

Gruß Thomas

--
Email: thomas-rapp@web.de
Home: thomas-rapp.homepage.t-online.de/

[ - Antworten - Zitieren - Direktlink - ]

28.01.2010, 14:11 Uhr

Der_Wanderer
Posts: 1229
Nutzer
Beides ist möglich und auch notwendig.

Ein Video Player würde aus eigenem Antrieb den Custom View neu bemalen, wenn nämlich ein Bild fertig decodiert ist.

Ein Bildanzieger würde den Custom View nur dann neu zeichnen, wenn man das Fenster re-sized oder die Verdeckung sich ändert oder das Custom View aus anderen Gründen zerstört worden ist. NTUI schickt daraufhin die entsprechende Refresh Message.

--
HD-Rec, Sweeper, Samplemanager, ArTKanoid, Monkeyscript, Toadies, AsteroidsTR, TuiTED, PosTED, TKPlayer, AudioConverter, ScreenCam, PerlinFX, MapEdit, AB3 Includes und viele mehr...
Homepage: http://www.hd-rec.de


[ - Antworten - Zitieren - Direktlink - ]

28.01.2010, 14:14 Uhr

Der_Wanderer
Posts: 1229
Nutzer
@whose

Nicht jedes tuiObjekt hat einen eigenen Thread am laufen.
Bisher gibt es nur den Hauptthread, wenn der GetEvent() aufruft wird alles anstehende erledigt. Plan ist, einen zweiten Thread laufen zu lassen, der trivale Dinge schon vorher erledigen kann, wie z.B. den Zustand eines gedrückten Buttons neu zeichnen, damit die GUI responsiver ist, wenn die Applikation gerade mal "nicht kann".

Eigentlich wirkt es nur schneller, aber das visuelle Feedback erlaubt schnelleres Arbeiten, da man bereits den Knopfdruck im Gehirn abhacken kann. Ohne visuelles Feedback ist man geneigt abzuwarten, ob es nun auch wirklich geklappt hat mit dem Knopfdruck.
Viele interne Aktionen kann man ja weder sehen noch fühlen, da kommt das das visuelle Feedback subjektiv dem Erledigen der Aktion bereits gleich.

--
HD-Rec, Sweeper, Samplemanager, ArTKanoid, Monkeyscript, Toadies, AsteroidsTR, TuiTED, PosTED, TKPlayer, AudioConverter, ScreenCam, PerlinFX, MapEdit, AB3 Includes und viele mehr...
Homepage: http://www.hd-rec.de



[ Dieser Beitrag wurde von Der_Wanderer am 28.01.2010 um 14:17 Uhr geändert. ]

[ - Antworten - Zitieren - Direktlink - ]

28.01.2010, 14:41 Uhr

Holger
Posts: 8116
Nutzer
Zitat:
Original von Der_Wanderer:
Das funktioniert auch gut so, solange die Applikation nicht blockiert ist. Das ist ja der häufigste Kritikpunkt an MUI. Deshalb möchte ich, zumindest in der Version 2.0, das Abholen der Messages und das optische Reagieren der GUI in einem separaten Thread machen. Für den App Programmierer ist das natürlich alles transparent.

Geht aber nur dann transparent, wenn die Anwendung überhaupt nichts mit den ntui-Objekten machen darf. Andernfalls muss der Anwendungsprogrammierer davon wissen, denn er muss sämtliche Zugriffe mit einem entsprechenden Lock versehen.
Zitat:
Ich denke die Lösung mit "ntui_ObtainRastPort" ist wohl die beste.
D.h. der App Programmierer muss sich den RastPort jedesmal erfragen. So kann ich seine Zeichenoperationen auch beliebig umleiten, z.B. für DoubleBuffering.
Das sollte den App Programmierer ja nicht weiter stören. Irgendwoher muss er sich den RP ja sowieso besorgen.

Ja und irgendwie muss er wissen, in welchen Bereich er zeichnen darf und braucht vielleicht auch noch ein paar andere Informationen, die sich auf keinen Fall während des Zeichnens ändern dürfen.

Das alles muss ebenfalls gesperrt werden. Und deshalb sollte die zugehörige Funktion auch nicht auf den RastPort fixiert sein. Andernfalls wird dem Programmierer nicht bewusst, dass er erst den RastPort holen (den Status locken) muss, bevor er die anderen Informationen abholt.
Zitat:
NTUI soll so einfach wie nur irgendwie möglich für den App Programmierer sein. Also deutlich einfacher als BOOPSI oder MUI.
Mein Ziel ist es, dass der App Programmierer sich auf die App konzentriert, während es bei den meisten Amiga Toolkits schon fast die Hauptaufgabe der App ist, sich mit der GUI auseinanderzusetzen.

Das liegt daran, dass alle diese Toolkits bei null anfangen, in dem Irrglauben, dass man auf dem untersten Level irgendetwas wesentlich besser machen könnte, um die Programmierung auf dem obersten Level zu verbessern.

Und nach x Jahren Entwicklung sind sie dann da angekommen, wo die anderen Toolkits auch schon sind. Ohne wesentliche Verbesserungen.
Zitat:
Plan ist, einen zweiten Thread laufen zu lassen, der trivale Dinge schon vorher erledigen kann, wie z.B. den Zustand eines gedrückten Buttons neu zeichnen, damit die GUI responsiver ist, wenn die Applikation gerade mal "nicht kann".

Eigentlich wirkt es nur schneller, aber das visuelle Feedback erlaubt schnelleres Arbeiten, da man bereits den Knopfdruck im Gehirn abhacken kann. Ohne visuelles Feedback ist man geneigt abzuwarten, ob es nun auch wirklich geklappt hat mit dem Knopfdruck.

Ein bekanntes und auch schon durchgekautes Problem. Gegenbeispiel ist SFSSalv (ich weiß nicht, ob es neuere, verbesserte Versionen gibt), das eine halbe Stunde und mehr auf einer Partition rödeln konnte, ohne ein Feedback und ohne das GUI zu sperren. Da kann der Anwender nach Gutdünken auf die Buttons drücken, und bekommt für diese auch ein visuelles Feedback, aber sonst passiert auch nichts.

Das Fazit bleibt, dass kein Toolkit vernünftige Programmierung ersetzen kann.

--
Good coders do not comment. What was hard to write should be hard to read too.

[ - Antworten - Zitieren - Direktlink - ]

28.01.2010, 14:52 Uhr

Der_Wanderer
Posts: 1229
Nutzer
@DiskSalv

Ja, wenn man von vornherein weis, dass man längere Zeit nicht reagieren können wird, dann sollte man die Buttons (außer dem Abbruch Button) disablen, oder gleich das ganze Fenster und einen exklusiven Dialog mit Progressbar und Abbruch Button.
Evtl. käme dann auch ein Feature wie unter Windows gelegen, wo man nur einen Knopf drücken kann, dann wird das Fenster blockiert, wenn die Message nicht innerhalb eines kurzen Zeit abgeholt wird, solange bis die Applikation wieder Messages abholt. (automatischer Busy Pointer)

Ausser Feelin (was sehr ähnliches Konzept wie NTUI hat) gibt es aber unter OS3.x kein GUI Toolkit mehr, das weiterentwicklet wird. Und allen Toolkits fehlen Dinge wie AlphaChannel Support, Skins etc.

--
HD-Rec, Sweeper, Samplemanager, ArTKanoid, Monkeyscript, Toadies, AsteroidsTR, TuiTED, PosTED, TKPlayer, AudioConverter, ScreenCam, PerlinFX, MapEdit, AB3 Includes und viele mehr...
Homepage: http://www.hd-rec.de


[ - Antworten - Zitieren - Direktlink - ]

28.01.2010, 15:58 Uhr

whose
Posts: 2156
Nutzer
@Der_Wanderer:

Ah, im Groben habe ichs also begriffen, ok.

Ich schätze, ganz wirst Du ohne irgendwelche Arbitration nicht auskommen und mit hoher Wahrscheinlichkeit wird das das eine oder andere "lästige Übel" für den Applikationsprogrammierer mit sich bringen.

Und zur Argumentation in Sachen Feedback: Sag besser, was Du schon sagtest... Weil kein anderes GUI-Toolkit unter OS3.x noch Weiterentwicklung erfährt.

Die Feedback-Geschichte funktioniert unter BOOPSI ja schon so, denn für das Feedback eines GUI-Elements braucht es auch da prinzipiell keinen Eingriff der Applikation.

An Deiner Stelle würde ich mich mehr um die Komfortfunktionen kümmern als darum, daß der Applikationscoder eventuell einen Parameter mehr mit "herumschleppen" muß. Wer sich darüber mokiert, aber gleichzeitig fast nen Orgasmus bekommt, wenn von wxWidgets & Co. die Rede ist, hat meiner Meinung nach eh was am Sträußchen...
--
---

:boing: µA1 PPC 750GX-800
:boing: A4000 PPC 604e-233

[ - Antworten - Zitieren - Direktlink - ]


-1- 2 [ - Beitrag schreiben - ]


amiga-news.de Forum > Programmierung > RastPort und Multithreading [ - Suche - Neue Beiträge - Registrieren - Login - ]


.
Impressum | Datenschutzerklärung | Netiquette | Werbung | Kontakt
Copyright © 1998-2024 by amiga-news.de - alle Rechte vorbehalten.
.