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

amiga-news.de Forum > Programmierung > Images auf einem Fenster [ - Suche - Neue Beiträge - Registrieren - Login - ]

1 2 -3- 4 [ - Beitrag schreiben - ]

06.11.2005, 01:35 Uhr

NoImag
Posts: 1050
Nutzer
@all:

Mir ist der Unterschied zwischen Wait und WaitPort schon klar. Ich benutze beides jeweils dort, wo es angebracht ist. Ich bezog mich auf eine Aussage, die sowohl in den RKMS als auch in den Autodocs zu WaitPort steht (hier Zitat aus den Autodocs zu WaitPort):

Zitat:
More than one message may be at the port when this returns. It is proper to call the GetMsg() function in a loop until all messages have been handled, then wait for more to arrive.

Tschüß,


[ - Antworten - Zitieren - Direktlink - ]

06.11.2005, 16:47 Uhr

geit
Posts: 332
[Ex-Mitglied]
Zitat:
Original von NoImag:
@all:

Mir ist der Unterschied zwischen Wait und WaitPort schon klar. Ich benutze beides jeweils dort, wo es angebracht ist. Ich bezog mich auf eine Aussage, die sowohl in den RKMS als auch in den Autodocs zu WaitPort steht (hier Zitat aus den Autodocs zu WaitPort):

Zitat:
More than one message may be at the port when this returns. It is proper to call the GetMsg() function in a loop until all messages have been handled, then wait for more to arrive.

Tschüß,


Natürlich muß man das so machen:

while(1) {
WaitPort();
while( msg=GetMsg() ) {
....
ReplyMsg( msg);
}
}

Es kann mehr als eine Message am Port anliegen, aber man muß und sollte kein WaitPort() ausführen, weil Pollen schneller ist. Man bekommt auch alle Nachrichten, die auflaufen, während man in der GetMsg()/ReplyMsg() Schleife ist.

Geit




[ Dieser Beitrag wurde von geit am 06.11.2005 um 16:48 Uhr editiert. ]

[ - Antworten - Zitieren - Direktlink - ]

06.11.2005, 18:58 Uhr

Holger
Posts: 8116
Nutzer
Zitat:
Original von NoImag:
Zitat:
More than one message may be at the port when this returns. It is proper to call the GetMsg() function in a loop until all messages have been handled, then wait for more to arrive.

Das würde ich mit kann man machen übersetzen, nicht mit muß man machen.

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

[ - Antworten - Zitieren - Direktlink - ]

06.11.2005, 19:05 Uhr

Holger
Posts: 8116
Nutzer
Zitat:
Original von geit:
Natürlich muß man das so machen:

while(1) {
WaitPort();
while( msg=GetMsg() ) {
....
ReplyMsg( msg);
}
}

Muß man nicht.
Zitat:
Es kann mehr als eine Message am Port anliegen, aber man muß und sollte kein WaitPort() ausführen, weil Pollen schneller ist. Man bekommt auch alle Nachrichten, die auflaufen, während man in der GetMsg()/ReplyMsg() Schleife ist.
Wenn Du mir jetzt schlüssig begründen kannst, warum GetMsg schneller sein soll als der funktional absolut identische Test innerhalb von WaitPort, dann bleibt nur noch die Frage, warum man neuerding performant programmieren muß, vor allem bei Code-Stellen, deren Performance-Relevanz im Promille-Bereich liegt.
Aber ich bezweifle, daß es auch nur für den ersten Punkt eine ernstzunehmende Begründung gibt.

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

[ - Antworten - Zitieren - Direktlink - ]

06.11.2005, 20:42 Uhr

geit
Posts: 332
[Ex-Mitglied]
Zitat:
Original von Holger:
Zitat:
Original von geit:
Natürlich muß man das so machen:

while(1) {
WaitPort();
while( msg=GetMsg() ) {
....
ReplyMsg( msg);
}
}

Muß man nicht.
Zitat:
Es kann mehr als eine Message am Port anliegen, aber man muß und sollte kein WaitPort() ausführen, weil Pollen schneller ist. Man bekommt auch alle Nachrichten, die auflaufen, während man in der GetMsg()/ReplyMsg() Schleife ist.
Wenn Du mir jetzt schlüssig begründen kannst, warum GetMsg schneller sein soll als der funktional absolut identische Test innerhalb von WaitPort, dann bleibt nur noch die Frage, warum man neuerding performant programmieren muß, vor allem bei Code-Stellen, deren Performance-Relevanz im Promille-Bereich liegt.
Aber ich bezweifle, daß es auch nur für den ersten Punkt eine ernstzunehmende Begründung gibt.


Das ist der logische Ablauf.

Ich renne auch nicht 5 mal zum Briefkasten, wenn 5 Briefe drin liegen. Sondern nehme alle mit, wenn die Post da war.

Geit

[ - Antworten - Zitieren - Direktlink - ]

07.11.2005, 00:34 Uhr

NoImag
Posts: 1050
Nutzer
Zitat:
Original von Holger:
Zitat:
Original von NoImag:
Zitat:
More than one message may be at the port when this returns. It is proper to call the GetMsg() function in a loop until all messages have been handled, then wait for more to arrive.

Das würde ich mit kann man machen übersetzen, nicht mit muß man machen.

Ich habe das übersetzt mit: "Wer ein ordentlicher Programmierer sein will, der hat das so zu machen." War vielleicht etwas überinterpretiert. Aber geit scheint ja der Meinung zu sein, dass dies vernünftig ist. Wenn aber nur Performence-Gründe dafür sprechen, dann sehe ich das als nicht so wichtig an.

Tschüß,


[ - Antworten - Zitieren - Direktlink - ]

07.11.2005, 10:00 Uhr

MaikG
Posts: 5172
Nutzer
Kann mir einer noch kurz sagen wie man das unter C macht:

b&=12345678
A$="Test"+STR$(b&)

printf unterstützt ja nur CLI wollte aber gerne ins
Fenster mit Text schreiben.

[ - Antworten - Zitieren - Direktlink - ]

07.11.2005, 10:44 Uhr

thomas
Posts: 7716
Nutzer
@MaikG:

#include <stdio.h>

char a[20];
long b = 12345678;
sprintf (a,"Test%ld",b);

Gruß Thomas

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

[ - Antworten - Zitieren - Direktlink - ]

07.11.2005, 12:08 Uhr

Mad_Dog
Posts: 1944
Nutzer
Zitat:
Original von thomas:
@MaikG:

#include <stdio.h>

char a[20];
long b = 12345678;
sprintf (a,"Test%ld",b);


Er will's im Fenster haben, fehlt also noch ein Aufruf von Text().

z.B.:

Text(rp,a,sizeof(a));

--

http://www.norman-interactive.com

[ - Antworten - Zitieren - Direktlink - ]

07.11.2005, 12:30 Uhr

thomas
Posts: 7716
Nutzer
@Mad_Dog:

Dann mach es aber auch richtig:

Text(rp,a,strlen(a));

Sonst bekommst du lauter Rechtecke hinter den Text.

Gruß Thomas

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

[ - Antworten - Zitieren - Direktlink - ]

07.11.2005, 22:22 Uhr

Holger
Posts: 8116
Nutzer
Zitat:
Original von geit:
Ich renne auch nicht 5 mal zum Briefkasten, wenn 5 Briefe drin liegen. Sondern nehme alle mit, wenn die Post da war.

Das ist vollkommener Unsinn. Wir reden hier über Programmierung und nicht über einen mehrere Meter entfernten Briefkasten. Wenn Du bei dem Beispiel bleiben willst, dann bedeutet GetMsg() ebenfalls zum Briefkasten rennen. Beide Funktionen sind Systemfunktionen mit demselben initialen Overhead.
GetMsg() heißt "renne zum Briefkasten und bringe einen Brief mit, wenn einer da ist."
WaitPort() heißt "renne zum Briefkasten und warte, wenn kein Brief da ist."
Nur, daß Du beim Aufruf von GetMsg() in einer Schleife am Ende einmal umsonst rennst, weil kein Brief da ist.
Für genau eine Iteration des Event-Loops bedeutet das, daß bei Deiner Vorgehensweise immer genau einmal umsonst zum Briefkasten gerannt wurde, während beim unbedingten Aufrufen von WaitPort() einem GetMsg() möglicherweise umsonst zum Briefkasten gerannt wurde.
Also unterm Strich gewinnt die Variante "jedesmal WaitPort() aufrufen" den Wettbewerb "höchste Performance im nicht meßbaren Bereich" klar nach Punkten.

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

[ - Antworten - Zitieren - Direktlink - ]

07.11.2005, 23:53 Uhr

MaikG
Posts: 5172
Nutzer
Text läuft auch. Danke.

[ - Antworten - Zitieren - Direktlink - ]

08.11.2005, 00:10 Uhr

Holger
Posts: 8116
Nutzer
Zitat:
Original von NoImag:
Aber geit scheint ja der Meinung zu sein, dass dies vernünftig ist. Wenn aber nur Performence-Gründe dafür sprechen, dann sehe ich das als nicht so wichtig an.


Es gibt doch einen wichtigeren Grund, es so zu machen. Wenn man irgendwann mal im Zuge einer Erweiterung des Programms auf mehrere Signalquellen reagieren muß, spricht um Wait() nicht mehr herumkommt, besteht keine Gefahr mehr, daß man die nötige Änderung des GetMsg()-Teils vergißt.
Die Schleife mit NULL-Vortest funktioniert halt in beiden Fällen, egal ob man Wait() oder WaitPort() benutzt.

mfg

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

[ - Antworten - Zitieren - Direktlink - ]

08.11.2005, 00:59 Uhr

whose
Posts: 2156
Nutzer
@Holger:

Also sind wir uns im Grunde einig, daß Messages abgeholt werden sollten, wenn sie anliegen, das ist schön ;)

Die empfohlene Wait()-Schleife ist auch meiner Meinung nach der beste und sauberste Weg, damit umzugehen. Also sollte man das auch so machen, wenn keine wichtigen Gründe dagegen sprechen. Die Beispiele für AmigaOS-API- oder gar C-Anfänger bergen jedenfalls keinen konkreten Grund, auf WaitPort() auszuweichen und/oder das Abholen der Messages zu vernachlässigen.

Grüße

--
---

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

[ - Antworten - Zitieren - Direktlink - ]

08.11.2005, 08:53 Uhr

gni
Posts: 1106
Nutzer
Zitat:
Holger:
Also unterm Strich gewinnt die Variante "jedesmal WaitPort() aufrufen" den Wettbewerb "höchste Performance im nicht meßbaren Bereich" klar nach Punkten.

Damit hast Du klar nachgewiesen, das es also vollkommen gleich ist, was man benutzt. Schlußfolgerung: benutzte Wait().

[ Dieser Beitrag wurde von gni am 08.11.2005 um 08:56 Uhr editiert. ]

[ - Antworten - Zitieren - Direktlink - ]

08.11.2005, 09:28 Uhr

Mad_Dog
Posts: 1944
Nutzer
@MaikG:

Als kleinen Vorgeschmack auf die kommende Lektionen in meinem C Kurs poste ich hier mal ein Beispiel zum Thema Text und Fonts:

code:
/*  Listing 8.7.1
 *  Text und Fonts
 */

#include <stdio.h>

#include <exec/exec.h>
#include <exec/types.h>
#include <intuition/intuition.h>
#include <graphics/gfx.h>
#include <graphics/text.h>

#include <proto/intuition.h>
#include <proto/dos.h>
#include <proto/exec.h>
#include <proto/graphics.h>
#include <proto/diskfont.h>  // Funktionsprototypen der diskfont.library

// Symbolische Konstanten
#define WIDTH 300   // Breite des Fensters
#define HEIGHT 200  // Höhe des Fensters

struct Window *Fenster;                // Zeiger auf Window-Struktur
struct IntuitionBase *IntuitionBase;   // Zeiger auf IntuitionBase-Struktur
struct RastPort *rp;                   // Zeiger auf RastPort Struktur
struct Library *DiskfontBase;          // Zeiger auf DiskfontBase
struct TextFont *textfont;             // Zeiger auf TextFont
struct TextAttr ta;                    // TextAttr Struktur

int main(void)
{

  // Intuition Library öffnen
  IntuitionBase = (struct IntuitionBase *) OpenLibrary("intuition.library",37L);

  if (IntuitionBase != NULL)
  {

    // Fenster mittels Tags öffnen
    Fenster = OpenWindowTags(NULL,
                             WA_Left, 100,       // Abstand vom linken Rand
                             WA_Top, 100,        // Abstand vom oberen Rand
                             WA_Width, WIDTH,    // Breite
                             WA_Height, HEIGHT,  // Höhe
                             WA_Title, "Text ist auch Grafik", // Fenstertitel
                             WA_CloseGadget, TRUE,             // Close-Gadget
                             WA_DragBar, TRUE,                 // Ziehleiste
                             WA_DepthGadget, TRUE,             // Depth-Gadget
                             WA_IDCMP, IDCMP_CLOSEWINDOW,
                             WA_Activate, TRUE,                // Fenster aktivieren
                             TAG_DONE);

    // Disk Font Library öffnen
    DiskfontBase = OpenLibrary("diskfont.library",37L);

    if (Fenster != NULL)
    {
      rp = Fenster->RPort;

      /* TextAttr Struktur ausfüllen... */
      ta.ta_Name = "topaz.font";  // Name des Fonts
      ta.ta_YSize = TOPAZ_SIXTY;  // Höhe des Fonts
      ta.ta_Style = FS_NORMAL;    // Normaler Textstil
      ta.ta_Flags = FPF_ROMFONT;  // Es ist ein ROM-Font

      /* Die Funktion OpenFont öffnet ROM Fonts */
      textfont = (struct TextFont *) OpenFont(&ta);

      if (textfont != NULL)
      {
        SetFont(rp, textfont);             // Font setzen
        SetAPen(rp,1L);                    // Schriftfarbe wählen
        Move(rp,20,50);                    // Grafik Cursor bewegen
        Text(rp,"Das ist Topaz 60.",17);   // Text ausgeben
        ta.ta_YSize = TOPAZ_EIGHTY;        // Andere Höhe wählen
        Move(rp,20,70);
        Text(rp,"Und das ist Topaz 80.",21);
        CloseFont(textfont);               // Font schließen
      }
      else
      {
        printf("Fehler: Kann topaz.font nicht öffnen.\n");
      }

      /* TextAttr Struktur ausfüllen... */
      ta.ta_Name = "helvetica.font";  // Name des Fonts
      ta.ta_YSize = 24;               // Höhe des Fonts
      ta.ta_Style = FS_NORMAL;        // Normaler Textstil
      ta.ta_Flags = FPF_DISKFONT;     // Es ist ein Disk Font

      /* Die Funktion OpenDiskFont öffnet einen Font aus FONTS: */
      textfont = (struct TextFont *) OpenDiskFont(&ta);

      if (textfont != NULL)
      {
        SetFont(rp, textfont);
        SetAPen(rp,2L);
        Move(rp,20,110);
        Text(rp,"Helvetica 24",12);
        CloseFont(textfont);
      }
      else
      {
        printf("Fehler: Kann helvetica.font nicht öffnen.\n");
      }

      /* TextAttr Struktur ausfüllen... */
      ta.ta_Name = "courier.font";    // Name des Fonts
      ta.ta_YSize = 18;               // Höhe des Fonts
      ta.ta_Style = FS_NORMAL;        // Normaler Textstil
      ta.ta_Flags = FPF_DISKFONT;     // Es ist ein Disk Font

      textfont = (struct TextFont *) OpenDiskFont(&ta);

      if (textfont != NULL)
      {
        SetFont(rp, textfont);
        Move(rp,20,140);
        Text(rp,"Courier 18",10);
        CloseFont(textfont);
      }
      else
      {
        printf("Fehler: Kann courier.font nicht öffnen.\n");
      }

      // Auf Close-Gadget warten
      Wait(1L << Fenster->UserPort->mp_SigBit);

      CloseWindow(Fenster);   // Fenster schließen
    } // end if

  } // end if

  // Libraries schließen
  if (IntuitionBase != NULL) CloseLibrary((struct Library *)IntuitionBase);
  if (DiskfontBase != NULL)  CloseLibrary((struct Library *)DiskfontBase);

  return 0;

}


--

http://www.norman-interactive.com

[ - Antworten - Zitieren - Direktlink - ]

08.11.2005, 10:13 Uhr

MaikG
Posts: 5172
Nutzer
Danke das war genau das was mir als nächstes fehlte,
nun muss ich es nicht aus Basic übersetzen :-)

[ - Antworten - Zitieren - Direktlink - ]

08.11.2005, 10:55 Uhr

geit
Posts: 332
[Ex-Mitglied]
@Holger

> Das ist vollkommener Unsinn. Wir reden hier über Programmierung und nicht über einen mehrere Meter entfernten Briefkasten.
Komisch! In jedem Programmierkurs über Interrupts wird die Hausglocke verwendet. :)

> Wenn Du bei dem Beispiel bleiben willst, dann bedeutet GetMsg() ebenfalls zum Briefkasten rennen. Beide Funktionen sind Systemfunktionen mit demselben initialen Overhead.
> GetMsg() heißt "renne zum Briefkasten und bringe einen Brief mit, wenn einer da ist."
> WaitPort() heißt "renne zum Briefkasten und warte, wenn kein Brief da ist."
Nein! Ich warte auf den Postboten (WaitPort()) bzw. darauf das dieser das Fänchen daran (MP_SIGBIT) aufstellt und laufe zum Briefkasten. Dann laufe ich zum Briefkasten und ziehe einen Brief raus (GETMSG()) und prüfe auf Werbung (IDCMP_WERBUNG) oder Rechnung (IDCMP_RECHNUNG). Je nach Typ ignoriere oder öffne ich den Brief. Danach wandert der Kram in die Tonne (ReplyMSG()) und ich nehme den nächsten Brief.

Lustig sieht das aus, wenn der Postbote danebensteht und immer einen Brief reinwirft, während ich einen rausnehme. :)

>Nur, daß Du beim Aufruf von GetMsg() in einer Schleife am Ende einmal umsonst rennst, weil kein Brief da ist.
Umgekehrt wird ein Schuh draus. Wenn Du bei jedem Umlauf durch WaitPort läufst, hast Du bei jedem Umlauf eine Abfrage mehr gemacht als nötig.

>Also unterm Strich gewinnt die Variante "jedesmal WaitPort() aufrufen" den Wettbewerb "höchste Performance im nicht meßbaren Bereich" klar nach Punkten.
Wohl kaum. Zumal die offizielle Variante weitere Vorteile hat, bzw einige Seiteneffekte hat:

a) Wie bereits angesprochen kann man WaitPort() durch Wait() ersetzen ohne etwas ändern zu müssen.
b) WaitPort() ruft sowieso Wait() auf, daher ist Wait() immer schneller.
b) Nachrichten die Auflaufen oder vorhanden sind, während eine Nachricht bearbeitet wird, werden sofort und ohne Verzögerung bearbeitet.
c) Bei WaitPort() wird der Listenkopf auf eine Node geprüft, bei GetMSG() auch. Daher ist beides Zeitverschwendung. Das mag nicht viel erscheinen, aber gerade bei Timern oder IDCMP_INTUITICKS summiert sich das sehr schnell.

Damit man sieht was in WaitPort() so passiert hier ein Stück aus dem Kick 1.2 Dump von Markus Wandel

---------------------------------------------------------------------- -----
message = WaitPort( port )
D0 A0
---------------------------------------------------------------------- -----
FC1BF6 move.l $14(A0),A1 Get head pointer of port's message list.
FC1BFA tst.l (A1) Check if list is empty.
FC1BFC bne.s FC1C1A If not empty, return right away.

FC1BFE move.b $0F(A0),D1 List was empty. Get signal bit.
FC1C02 lea $14(A0),A0 Point A0 at message list.
FC1C06 moveq #0,D0
FC1C08 bset D1,D0 Compute signal mask.
FC1C0A move.l A2,-(SP)
FC1C0C move.l A0,A2
FC1C0E jsr -$013E(A6) Wait()
FC1C12 move.l (A2),A1
FC1C14 tst.l (A1) Check message list.
FC1C16 beq.s FC1C0E If still empty, go back and wait again.
FC1C18 move.l (SP)+,A2
FC1C1A move.l A1,D0 Return first message in the list.
FC1C1C rts

@Mad Dog

Funktioniert! :)

Geit

[ - Antworten - Zitieren - Direktlink - ]

09.11.2005, 00:59 Uhr

Holger
Posts: 8116
Nutzer
Zitat:
Original von geit:
Nein! Ich warte auf den Postboten (WaitPort()) bzw. darauf das dieser das Fänchen daran (MP_SIGBIT) aufstellt und laufe zum Briefkasten.

Mich würde mal interessieren, welche reale Operation der Software Du mit dem "zum Briefkasten laufen" assoziierst.
GetMsg() liefert außschließlich den Head-Eintrag der Message-Liste, also muß es ja wohl das sein.
Und genau das tut WaitPort() ebenfalls, und zwar, wie ich es auch sagte, als erstes.
Zitat:
Umgekehrt wird ein Schuh draus. Wenn Du bei jedem Umlauf durch WaitPort läufst, hast Du bei jedem Umlauf eine Abfrage mehr gemacht als nötig.
Wenn keine Message da ist, mußt Du warten. Es ist also nicht "mehr als nötig".
Wenn Du GetMsg() in einer Schleife ausführst, bis NULL zurückgeliefert wird, hast Du immer eine Abfrage mehr. Und komme nicht mit, "könnte ja sein, daß immer eine neue Message da ist". Das hieße, das der Rechner ständig mit 100% CPU-Last fährt. Das ist unrealistisch.
Zitat:
b) WaitPort() ruft sowieso Wait() auf, daher ist Wait() immer schneller.
Vielleicht erhellt das, warum Du die Argumente so verdrehst. Du vergleichst die Performance von Wait() und WaitPort(). Das war aber überhaupt nicht das Thema. Es ging um die Frage "soll man immer eine GetMsg()-Schleife ausführen, bis NULL kommt, oder jedesmal WaitPort() aufrufen". Das betrifft ausschließlich den Fall, wenn man WaitPort() benutzt. Die Performance von Wait() ist dabei vollkommen irrelevant.
Zitat:
b) Nachrichten die Auflaufen oder vorhanden sind, während eine Nachricht bearbeitet wird, werden sofort und ohne Verzögerung bearbeitet.
Da WaitPort() überhaupt keine Verzögerung erzeugt, wenn eine Message "aufgelaufen" ist, ist das kein Argument.
Zitat:
c) Bei WaitPort() wird der Listenkopf auf eine Node geprüft, bei GetMSG() auch. Daher ist beides Zeitverschwendung.
Das ist ein sinnloses Argument. Wie sieht denn jetzt Dein Gegenvorschlag aus? Kein Test durchführen und auf NULL zugreifen? Einen Message-Loop ohne GetMsg() programmieren?
Auf diese sogenannte Zeitverschwendung kann überhaupt nicht verzichtet werden.
Nachtrag:
Falls Du den "Overhead" meinst, daß bei der direkten Abfolge von WaitPort(), GetMsg() zwei NULL-Tests durchgeführt werden: nun, dafür kann ich in dieser Variante auf den NULL-Test des Resultats von GetMsg() verzichten. Unterm Strich exakt genauso viele NULL-Tests bei beiden Varianten.
Daß bei der Verwendung von Wait() mit der Schleife ein Test eingespart werden kann: nun, einem Anfänger zu erklären, daß er diese kompliziertere Variante benutzen soll, weil er zwei oder drei Assembler-Befehle damit einspart, halte ich nicht für sinnvoll.
Alle Fortgeschrittenen Beispiele verwenden ja aus anderen Gründen sowieso nur noch Wait().
Zitat:
Damit man sieht was in WaitPort() so passiert hier ein Stück aus dem Kick 1.2 Dump von Markus Wandel
Wie man unschwer erkennt, kehrt diese Funktion sofort zurück, wenn Messages anliegen. Stellt also überhaupt keine Verzögerung oder gar Performance-Bremse dar.

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

[ Dieser Beitrag wurde von Holger am 09.11.2005 um 01:08 Uhr editiert. ]

[ - Antworten - Zitieren - Direktlink - ]

09.11.2005, 01:21 Uhr

NoImag
Posts: 1050
Nutzer
Zitat:
Original von gni:
Zitat:
Holger:
Also unterm Strich gewinnt die Variante "jedesmal WaitPort() aufrufen" den Wettbewerb "höchste Performance im nicht meßbaren Bereich" klar nach Punkten.

Damit hast Du klar nachgewiesen, das es also vollkommen gleich ist, was man benutzt. Schlußfolgerung: benutzte Wait().

Du vergisst hier, dass WaitPort den Vorteil hat, nur dann zurückzukehren, wenn auch tatsächlich eine Message anliegt. Wenn man nur an einen MessagePort und keinen anderen Signals interessiert ist, dann ist WaitPort deshalb die bessere Wahl.

Tschüß,


[ - Antworten - Zitieren - Direktlink - ]

09.11.2005, 01:27 Uhr

geit
Posts: 332
[Ex-Mitglied]
Zitat:
Zitat:
Damit man sieht was in WaitPort() so passiert hier ein Stück aus dem Kick 1.2 Dump von Markus Wandel
Wie man unschwer erkennt, kehrt diese Funktion sofort zurück, wenn Messages anliegen.

Komisch! Oben hast Du gemeint, das man einen unnützen Aufruf von GetMsg() macht, der aber nichts anderes macht, als das was der WaitPort() macht, wenn eine Message anliegt.

Das hat Dich gestört, weil es einmal umsonst aufgerufen wird. Das es bei jeder (!) Message in WaitPort() gemacht wird, stört Dich aber nicht.

Also entweder einmal unnütz pro Umlauf oder pro Message ein mal unnütz. Da ist die klassische Abfrage durchaus sinnvoll.

Zitat:
Stellt also überhaupt keine Verzögerung oder gar Performance-Bremse dar.

Bei einem Umlauf nicht, aber wenn man Intuiticks oder Mouse IDCMPs hat, dann schon, weil diese kleine Abfrage 2 mal für jede Message gemacht wird.

Geit


[ - Antworten - Zitieren - Direktlink - ]

09.11.2005, 01:32 Uhr

geit
Posts: 332
[Ex-Mitglied]
Zitat:
Original von NoImag:
Zitat:
Original von gni:
Zitat:
Holger:
Also unterm Strich gewinnt die Variante "jedesmal WaitPort() aufrufen" den Wettbewerb "höchste Performance im nicht meßbaren Bereich" klar nach Punkten.

Damit hast Du klar nachgewiesen, das es also vollkommen gleich ist, was man benutzt. Schlußfolgerung: benutzte Wait().

Du vergisst hier, dass WaitPort den Vorteil hat, nur dann zurückzukehren, wenn auch tatsächlich eine Message anliegt. Wenn man nur an einen MessagePort und keinen anderen Signals interessiert ist, dann ist WaitPort deshalb die bessere Wahl.


Also mir fällt im Moment kein einziger sinnvoller Grund ein, WaitPort überhaupt in einem Programm zu benutzen. Das Programm würde sich nicht mehr abbrechen lassen, was eindeutig ein schlechter Programmierstil ist.

CTRL-C sollte immer gehen.

Geit

[ Dieser Beitrag wurde von geit am 09.11.2005 um 01:32 Uhr editiert. ]

[ - Antworten - Zitieren - Direktlink - ]

09.11.2005, 09:13 Uhr

Holger
Posts: 8116
Nutzer
Zitat:
Original von geit:
Komisch! Oben hast Du gemeint, das man einen unnützen Aufruf von GetMsg() macht, der aber nichts anderes macht, als das was der WaitPort() macht, wenn eine Message anliegt.

Das hat Dich gestört, weil es einmal umsonst aufgerufen wird. Das es bei jeder (!) Message in WaitPort() gemacht wird, stört Dich aber nicht.

Also entweder einmal unnütz pro Umlauf oder pro Message ein mal unnütz. Da ist die klassische Abfrage durchaus sinnvoll.

Ich habe den NULL-Test niemals als Performance-Bremse angesehen. Ich halte das für eine vollkommen sinnlose Diskussion. DU bist es, der über so einen Unsinn diskutieren will.
Ich sage nur, wenn Du unbedingt die NULL-Tests zählen willst, dann wirst DU auch bei objektiver Betrachtung feststellen, daß die WaitPort()->GetMsg() gegenüber der WaitPort()->while(GetMsg()) Variante weniger besitzt.
Nur wenn ständig neue Messages anliegen und Wait() unterm Strich wirklich nie gebraucht werden würde, würden weniger Tests auftreten.
Aber nochmal: das ist unrealistisch Auch bei Timern oder IntuiTicks passiert das nicht nicht. Wenn ein Programm jedesmal eine neue Message vorfindet, wenn es die letzte bearbeitet hat, hieße das, daß es am CPU-Limit arbeitet und jede weitere noch so kleine Verzögerung das System zusammenbrechen läßt, weil dann die Queue voll läuft und gar nicht mehr bearbeitet werden kann.

Zitat:
Bei einem Umlauf nicht, aber wenn man Intuiticks oder Mouse IDCMPs hat, dann schon, weil diese kleine Abfrage 2 mal für jede Message gemacht wird.

Nochmal, Du tauscht den Test in WaitPort gegen den Test in Deiner while(GetMsg()!=NULL) - Schleife ein. Bist Du echt so merkbefreit?

Nochmal antworte ich darauf nicht, mir wird das jetzt zu blöd.

Zitat:
Also mir fällt im Moment kein einziger sinnvoller Grund ein, WaitPort überhaupt in einem Programm zu benutzen. Das Programm würde sich nicht mehr abbrechen lassen, was eindeutig ein schlechter Programmierstil ist.

CTRL-C sollte immer gehen.


Das ist wohl für 99% aller Anwendungen richtig. Außer bei muti-threaded Anwendungen bei denen halt nur das Hauptprogramm auf CTRL-C reagieren muß. Und auch dieses nicht, wenn es bereits in der Beendigungphase ist, und nur noch auf confirm-Messages der Sub-Tasks wartet.
Natürlich kann man auch dort Wait() verwenden. Muß man aber nicht.

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

[ Dieser Beitrag wurde von Holger am 09.11.2005 um 09:15 Uhr editiert. ]

[ - Antworten - Zitieren - Direktlink - ]

09.11.2005, 13:05 Uhr

geit
Posts: 332
[Ex-Mitglied]
Zitat:
Nochmal, Du tauscht den Test in WaitPort gegen den Test in Deiner while(GetMsg()!=NULL) - Schleife ein. Bist Du echt so merkbefreit?

Nochmal antworte ich darauf nicht, mir wird das jetzt zu blöd.


Was der Compiler aus dem Systemfunktions Aufruf macht, ist also egal, war?

Im übrigen finde ich es gut, dass Du nicht mehr darauf antworten willst.

Beleidigen lassen kann ich mich auch woanders.

Geit

[ - Antworten - Zitieren - Direktlink - ]

10.11.2005, 00:13 Uhr

NoImag
Posts: 1050
Nutzer
Zitat:
Original von geit:
Also mir fällt im Moment kein einziger sinnvoller Grund ein, WaitPort überhaupt in einem Programm zu benutzen. Das Programm würde sich nicht mehr abbrechen lassen, was eindeutig ein schlechter Programmierstil ist.

CTRL-C sollte immer gehen.


Natürlich ist es wünschenswert, wenn sich ein Programm jederzeit abbrechen lässt. Dies hat aber nichts mit einer Ctrl-C-Abfrage in einer Warteschleife zu tun, sondern damit, ob das Programm auch dann auf Benutzereingaben lauscht, wenn es gerade beschäftigt ist.

Unter AmigaOS bringt Ctrl-C bei einem Programm mit grafischer Benutzeroberfläche keinerlei nutzen und ist deshalb überflüssig: Weshalb solltest du ein Programm abbrechen wollen, das du einfach nur beenden musst?

Tschüß,


[ - Antworten - Zitieren - Direktlink - ]

10.11.2005, 00:49 Uhr

geit
Posts: 332
[Ex-Mitglied]
Zitat:
Original von NoImag:
Zitat:
Original von geit:
Also mir fällt im Moment kein einziger sinnvoller Grund ein, WaitPort überhaupt in einem Programm zu benutzen. Das Programm würde sich nicht mehr abbrechen lassen, was eindeutig ein schlechter Programmierstil ist.

CTRL-C sollte immer gehen.


Natürlich ist es wünschenswert, wenn sich ein Programm jederzeit abbrechen lässt. Dies hat aber nichts mit einer Ctrl-C-Abfrage in einer Warteschleife zu tun, sondern damit, ob das Programm auch dann auf Benutzereingaben lauscht, wenn es gerade beschäftigt ist.

Unter AmigaOS bringt Ctrl-C bei einem Programm mit grafischer Benutzeroberfläche keinerlei nutzen und ist deshalb überflüssig: Weshalb solltest du ein Programm abbrechen wollen, das du einfach nur beenden musst?


Während der Laufzeit ist es natürlich um so wichtiger, aber das passiert meistens ja nicht, weil sowieso regelmäßig Updates in Fenstern etc. gemacht werden, die es erlauben CTRL-C abzufragen.

Was die Benutzeroberflächen angeht: Ich persönlich starte fast alle Programme via CLI. Oft breche ich die auch via CTRL-C oder Status/Break wieder ab. Das würde mir schon aufstoßen, wenn das nicht ginge.

AmigaOS zeichnet sich durch flexible Nutzungsmöglichkeiten aus. Die Shell und das DOS ist Bestandteil des OS und nicht nur Untersatz. Daher sollte man diese Flexibilität auch waren.

Geit



[ Dieser Beitrag wurde von geit am 10.11.2005 um 00:51 Uhr editiert. ]

[ - Antworten - Zitieren - Direktlink - ]

10.11.2005, 11:37 Uhr

Holger
Posts: 8116
Nutzer
Zitat:
Original von NoImag:
Unter AmigaOS bringt Ctrl-C bei einem Programm mit grafischer Benutzeroberfläche keinerlei nutzen und ist deshalb überflüssig: Weshalb solltest du ein Programm abbrechen wollen, das du einfach nur beenden musst?


Warum Kommandos über ARexx-Ports unterstützen, wenn man einfach nur den Menüpunkt auswählen/Button drücken muß?

Und wofür zur Hölle sollte man mehr als 640kB jemals benötigen? ;)

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

[ - Antworten - Zitieren - Direktlink - ]

13.11.2005, 00:59 Uhr

NoImag
Posts: 1050
Nutzer
Zitat:
Original von geit:
Was die Benutzeroberflächen angeht: Ich persönlich starte fast alle Programme via CLI. Oft breche ich die auch via CTRL-C oder Status/Break wieder ab. Das würde mir schon aufstoßen, wenn das nicht ginge.

AmigaOS zeichnet sich durch flexible Nutzungsmöglichkeiten aus. Die Shell und das DOS ist Bestandteil des OS und nicht nur Untersatz. Daher sollte man diese Flexibilität auch waren.


Wenn du es magst, dass nach einem Ctrl-C in der Shell das Programm noch einen Requester öffnet, um dich zu fragen, ob du deine Arbeit nicht doch lieber speichern willst - ich mag keine Mischung aus Shell und grafischer Oberfläche. Über Geschmack lässt sich aber natürlich nicht streiten.

Ich halte die Benutzung von Ctrl-C zum Beenden eines Programmes aber für einen Missbrauch dieser Funktion, unabhängig davon, ob ein Programm aus der Shell oder über die Workbench gestartet wurde. Wenn ein Shell-Programm durch das betätigen von "q" beendet werden kann, dann sollte man meiner Meinung nach nicht stattdessen Ctrl-C benutzen. Das brauchen wir aber nicht ausdiskutieren.

Tschüß,


[ - Antworten - Zitieren - Direktlink - ]

13.11.2005, 01:09 Uhr

NoImag
Posts: 1050
Nutzer
Zitat:
Original von Holger:
Zitat:
Original von NoImag:
Unter AmigaOS bringt Ctrl-C bei einem Programm mit grafischer Benutzeroberfläche keinerlei nutzen und ist deshalb überflüssig: Weshalb solltest du ein Programm abbrechen wollen, das du einfach nur beenden musst?


Warum Kommandos über ARexx-Ports unterstützen, wenn man einfach nur den Menüpunkt auswählen/Button drücken muß?

Und wofür zur Hölle sollte man mehr als 640kB jemals benötigen? ;)


Sollte unter AOS tatsächlich einmal mehr als 640kB benötigt werden, dann werde ich meine Software anpassen. ;)

Aber ernsthaft: Ein ARexx-Port bietet erheblich mehr Funktionalität als Ctrl-C. Mit Ctrl-C kann nur das Programm beendet werden, ohne weitere Beeinflussungsmöglichkeit des Programms. Ich halte den Vergleich daher für nicht passend. Hinzu kommt, dass auch das Beenden mit Ctrl-C nichtmal richtig funktioniert. Wenn gerade ein ASL-Requester offen ist, dann beendet sich das Programm nicht sofort (oder habe ich da irgendwas übersehen?). Ctrl-C ist zur Fernsteuerung eines Programmes daher gar nicht geeignet.

Um auf die Frage zurückzukommen, ob in jeder Warteschleife Ctrl-C abgefangen werden muss: Weil Ctrl-C bei ASL-Requestern nicht unmittelbar wirkt, ist es sogar notwendig, bei eigenen Requestern genauso zu verfahren, um ein konsistentes Verhalten des Programms sicherzustellen.

Tschüß,



[ Dieser Beitrag wurde von NoImag am 13.11.2005 um 01:11 Uhr editiert. ]

[ - Antworten - Zitieren - Direktlink - ]

13.11.2005, 14:14 Uhr

platon42
Posts: 400
[Ex-Mitglied]
Zitat:
Unter AmigaOS bringt Ctrl-C bei einem Programm mit grafischer Benutzeroberfläche keinerlei nutzen und ist deshalb überflüssig: Weshalb solltest du ein Programm abbrechen wollen, das du einfach nur beenden musst?

Alle Poseidon Tasks & Sub-Tasks lauschen auf Ctrl-C. Auch die graphischen Benutzeroberflächen. Das hat den banalen Hintergrund, dass z.B. für mein "Shutdown"-Script (wird über Reset-Handler ausgeführt, wenn ich Ctrl-LAmiga-RAmiga drücke) an alles Prozesse ein Ctrl-C geschickt wird -- was dazu führt, dass sich alle Programme sauber beenden (btw: auch YAM und IBrowse reagieren auf Ctrl-C -- und das ist gut so).

Sprich, man hat also einen Mechanismus, mit dem man das Zeug los wird, und muss sich nicht mühsam den ARexx-Port suchen und ein QUIT Kommando absetzen.

Zur WaitPort()/Wait() Geschichte: Jeder nach seiner Façon, ich selbst bin ein Wait()-Mensch. Die Performance-Unterschiede sind eher akademisch.
--
--
Best Regards

Chris Hodges

[ - Antworten - Zitieren - Direktlink - ]


1 2 -3- 4 [ - Beitrag schreiben - ]


amiga-news.de Forum > Programmierung > Images auf einem Fenster [ - Suche - Neue Beiträge - Registrieren - Login - ]


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