- fchao-Sinus-Wechselrichter AliExpress         
Seite 1 von 3 123 LetzteLetzte
Ergebnis 1 bis 10 von 22

Thema: Verlassen einer Funktion um später zurück zu springen.

  1. #1
    Neuer Benutzer Öfters hier
    Registriert seit
    24.05.2012
    Beiträge
    14

    Verlassen einer Funktion um später zurück zu springen.

    Anzeige

    Powerstation Test
    Ist es möglich eine Funktion an einem vorher definierten Punkt zu verlassen um dann später die Ausführung nach diesem Punkt wieder fortzuführen?

    Mein Problem ist folgendes: ich habe einen JobStack auf den ich Funktionen lege, damit diese nicht im aktuellen Kontext ausgeführt werden (z.B. um den Kontext aus einer ISR zu verschieben). Der JobStack wird dann im Main-Loop abgearbeitet. Um den Main-Loop nicht zu lange zu blockieren Suche ich eine Möglichkeit, Punkte in der Funktion festlegen, an denen die Funktion verlassen wird.

    Wird ein solcher Punkt erreicht, soll der JobStack die Kontrolle zurück an den Main-Loop geben. Nach dem der nächsten Iteration des Main-Loops soll der JobStack dann wieder an den vorher verlassenen Punkt springen und die Funktion fertig (oder bis zum nächsten "Break"-Point) ausführen.

    Ist sowas (mit vertretbarem Aufwand) überhaupt möglich und wenn ja wie Sinnvoll?

    MfG Iqon

  2. #2
    Erfahrener Benutzer Robotik Einstein Avatar von i_make_it
    Registriert seit
    29.07.2008
    Ort
    Raum DA
    Alter
    56
    Beiträge
    2.814
    Eine Hochsprachen Funktion (z.B. C++) hat genau einen Einsprungspunkt und mindestens einen Aussprungspunkt. Return kann man machen, wenn z.B. eine Funktion in einem Prüfzweig feststellt das sie vorzeitig verlassen werden kann. Nehmen wir C++ wo es Überladungen gibt, dann stellen wir fest, das ein Einsprung in eine Funktion an einer anderen Stelle als dem Funktionsaufruf nicht funktionieren kann, da der Compiler bei einer überladenen Funktion anhand der Argumente entscheidet welche der Funktionen nun aufzurufen ist. diese Bedingung ist so nicht mehr gegeben. unabhängig davon ob es Comilerfehler gibt, ist das Spagetticode den man spätestens 12 Monate nach dem man sich nicht mehr damit befasst hat, selbst nicht mehr versteht. Eventuell überlegen, ob man da wirklich eine Funktion nimmt, oder mehrere bzw. ob man die Funktion überläd und so beim Aufruf mit vorverarbeiteten Argumenten weiterlaufen lassen kann.

    Von der Beschreibung her, soll ja die Funktion bei jedem Durchlauf der Hauptschleife genau einmal aufgerufen werden. Wie stellst Du dir da die Weiterverarbeitung vor? Ändern sich da nicht bei jedem Aufruf die Werte der Argumente?
    Bzw. Was hast Du in der Hauptschleife untergebracht was Zeitkritisch ist. wäre es da nicht sinnvoll das mit Interrupts zu händlen. Wenn kein Event Interrupt, dann einen Timerinterrupt der zyklich dafür sorgt das man nichts wichtiges verpasst. Das Zielsystem auf dem der Code läuft, könnte auch eine Lösung liefern. Bei einem Multicoresystem, könnte man die betreffende Funktion exklusiv einen Core zuweisen, dann läuft sie parallel zum Rest des Programms.

  3. #3
    Erfahrener Benutzer Roboter-Spezialist Avatar von witkatz
    Registriert seit
    24.05.2006
    Ort
    NRW
    Alter
    54
    Beiträge
    542
    Blog-Einträge
    17
    Ich weiss nicht, ob ich dein Problem richtig verstehe, aber wäre das nicht ein Fall für eine State Machine? Im Unterprogramm können die Arbeitsabschnitte in einer switch-case Anweisung gegliedert werden. Wenn der jeweilige Arbeitsabschnitt abgearbeitet oder ein Ereignis eingetreten, setzt du die Switch-Variable auf den nächsten Wert und verlässt die Funktion.
    Gruß witkatz

  4. #4
    Neuer Benutzer Öfters hier
    Registriert seit
    24.05.2012
    Beiträge
    14
    Kein Multicore System. soll alles auf einem AVR laufen.
    Hier mal ein Pseudo-Code Beispiel wie ich mir das Vorstelle:

    Code:
    void longrunning(void) {
     ...
    }
    
    
    void main(void) {
    
    jobstack_put(&longrunnnig); while(true) {
    ... //Do something else jobstack_execute(); // this is the point where the jobstack functions are executed.
    }
    }
    Also führt jobstack_execute den aktuellen Job aus. Ich Suche jetzt nach einer einfachen Möglichkeit, "Longrunning Jobs" auszuführen ohne die Main zulange zu blockieren. Normalerweise würde so eine Funktion in einem eigenen Thread laufen und der Scheduler würde mein Problem lösen.

    Aber auf ein OS mit Threads will ich hier verzichten. Für meine Zwecke würde es reichen, wenn innerhalb des "Longrunning Jobs" Punkte angegeben werden, an denen die Ausführung pausiert werden darf.

    Code:
    void longrunning(void) {
    
    ... // do something CUSTOM_BREAK; ... // do something more }
    }
    Sobald CUSTOM_BREAK erreicht wird, soll jobstack_execute verlassen werden um noch einmal die Main-Schleife durch zu laufen. Wird jobstack_execute erneut aufgerufen, soll die Funktion longrunning direkt nach CUSTOM_BREAK wieder fortgesetzt werden.

    Im Moment sind das nur Gedankenspielereien ob das Überhaupt möglich ist. Wie aufwendig die implementierung wäre und ob ein solches Konzept überhaupt einen mehrwert bringen würde.

    - - - Aktualisiert - - -

    @i_make_it:
    Es geht hier auch nicht darum, andere Parameter zu übergeben, oder irgendetwas im Funktionsstack zu ändern. Ich will eine Funktionen während der ausführung unterbrechen und später "fertig ausführen".

    Im Moment ist auch nichts im Main-Loop. Ich will eine "flexible" Middleware für ein Projekt und bin am Überlegen ob so etwas Überhaupt möglich ist und wenn ja ob es den Aufwand auch Wert wäre.

    @witkatz:
    Glaube nicht das ne State Machine das Problem löst. Man könnte die einzelnen Abschnitte (vor und nach dem CUSTOM_BREAK zwar in einzelne States packen und die nacheinander abarbeiten. Aber das geht etwas an meinem Ziel vorbei . Ich will Funktionen mit minimalen Aufwand (=ein Macro) aufteilen können.
    Geändert von Iqon (17.09.2015 um 09:24 Uhr)

  5. #5
    Erfahrener Benutzer Robotik Visionär Avatar von oberallgeier
    Registriert seit
    01.09.2007
    Ort
    Oberallgäu
    Beiträge
    8.686
    Zitat Zitat von i_make_it Beitrag anzeigen
    Eine Hochsprachen Funktion (z.B. C++) hat genau einen Einsprungspunkt und mindestens einen Aussprungspunkt ... C++ wo es Überladungen gibt, dann stellen wir fest, das ein Einsprung in eine Funktion an einer anderen Stelle als dem Funktionsaufruf nicht funktionieren kann ...
    Meine Kenntnisse in C sind sehr begrenzt aber ich hab mich (vielleicht deshalb?) mit der Frage auch schon beschäftigt. Wegen mangelnden Zutrauens zu so einem Konstrukt hatte ich das nie getestet - auch nie geschrieben.

    Frage: KÖNNTE es nicht so gehen, dass man ein Flag mitschleppt? Beim Aufruf der Funktion informiert das Flag über die verschiedenen Zustände: Erster Aufruf, Aufruf nach Return am Ende des ersten Abschnittes, Aufruf nach Return am Ende des zweiten Abschnittes usf, Aufruf nach Abarbeiten der vollständigen Funktion. Ein switch nutzt nun diese Information zum Ansprung der verschiedenen Pseudoeingänge. Am Beginn jedes Cases wird dann das Flag erstmal passend gesetzt (?) und vor dem Break bzw. Return des aktuellen Cases (klingt aber jetzt irgendwie doppelt gemoppelt) wird das Flag entsprechend angepasst.

    Ich habs nie realisiert weil es mir irgendwie sehr seltsam vorkommt; wie sollte ich das testen??

    Nachtrag: Sorry, witzkatz ist schneller wach gewesen.
    Ciao sagt der JoeamBerg

  6. #6
    Erfahrener Benutzer Roboter-Spezialist Avatar von witkatz
    Registriert seit
    24.05.2006
    Ort
    NRW
    Alter
    54
    Beiträge
    542
    Blog-Einträge
    17
    Zitat Zitat von Iqon Beitrag anzeigen
    Ich will Funktionen mit minimalen Aufwand (=ein Macro) aufteilen können.
    So meinte ich das
    Code:
    void longrunning(void) {
        static step = 0;
        switch(step){
            case 0:
                /*...*/ // do something
                step++;
                break; //CUSTOM_BREAK;
            case 1:
                /*...*/ // do something more
                step = 0;
        }
    }
    Ist doch aufgeteilt, oder nicht?

  7. #7
    Neuer Benutzer Öfters hier
    Registriert seit
    24.05.2012
    Beiträge
    14
    Das mit dem "kaum pflegbar" würde ich nicht behaupten. Da die Funktionalität ja gut entkoppelt ist und auch sehr überschaubar. Mir schwebt da eine ähnliche Lösung (nur etwas leichter als deine) vor:

    1. Beim erreichen des Punktes wird die rücksprung Adresse in einem globalen Pointer gespeichert
    2. Zurück in die jobstack_execute und von da wieder in die Main
    3. Wird jobstack_execute erneut ausgeführt an den in Schritt 1 gesetzten Pointer springen

    Mein Problem hier ist, dass ich nicht weiß inwieweit ich damit mein Programm zerstöre. Muss ich vorher alle Register sichern, könnte ich Probleme mit den Funktions-Stack bekommen, ... .
    Welche Auswirkungen hat es, wenn ich eine Funktion einfach verlasse.

    - - - Aktualisiert - - -

    Zitat Zitat von witkatz Beitrag anzeigen
    Ist doch aufgeteilt, oder nicht?
    Ja ist aufgeteilt ist, bedeutet aber viel Aufwand in der Funktion und die Funktion wird dadurch sehr schwer lesbar.
    Der größte Nachteil dieser Lösung: Da die Funktion wirklich verlassen wird, verliert sie ihren Zustand. Will man zwischen den States zustände teilen muss das über globalen oder anderweitig geteilten Speicher geschehenm, was die Sache um einiges komplizierter macht.

  8. #8
    Erfahrener Benutzer Roboter-Spezialist Avatar von witkatz
    Registriert seit
    24.05.2006
    Ort
    NRW
    Alter
    54
    Beiträge
    542
    Blog-Einträge
    17
    Zitat Zitat von Iqon Beitrag anzeigen
    bedeutet aber viel Aufwand in der Funktion
    Nö, sehe ich nicht so.
    Zitat Zitat von Iqon Beitrag anzeigen
    und die Funktion wird dadurch sehr schwer lesbar.
    Im Gegenteil, es ist lesbarer als irgendein magisches Makro und gut debugbar mit Breakpoints in einzelnen Schritten. Aber wie meine Mutter immer zu sagen pflegte "de gustibus non est disputandum"
    Zitat Zitat von Iqon Beitrag anzeigen
    Da die Funktion wirklich verlassen wird, verliert sie ihren Zustand. Will man zwischen den States zustände teilen muss das über globalen oder anderweitig geteilten Speicher geschehenm, was die Sache um einiges komplizierter macht.
    static ?

  9. #9
    Erfahrener Benutzer Robotik Visionär Avatar von oberallgeier
    Registriert seit
    01.09.2007
    Ort
    Oberallgäu
    Beiträge
    8.686
    Zitat Zitat von Iqon Beitrag anzeigen
    Das mit dem "kaum pflegbar" würde ich nicht behaupten. Da die Funktionalität ja gut entkoppelt ist und auch sehr überschaubar ...
    Wäre also doch ne kleine Übung wert . . . wobei ich wohl die Version mit dem Flag brauche. Denn: Das Ergebnis der Funktion wird doch wohl (hoffentlich :.-.) ) von irgend einem Abschnitt benötigt. Und dieses Ergebnis ist nur dann gültig bzw. aktuell und brauchbar, wenn das Flag "Funktion mindestens einmal vollständig durchlaufen" gesetzt ist.

    Gute Mutter: "de gustibus non est disputandum" - meine verstand kein Latein, da musste ich selbst durch.
    Ciao sagt der JoeamBerg

  10. #10
    Neuer Benutzer Öfters hier
    Registriert seit
    24.05.2012
    Beiträge
    14
    Ja das Ergebnis wird benötitg. Der JobStack den ich nutze ruft Funktionen mit folgender Signatur auf:
    Code:
    void (*jobstack_job)(void *dataPtr)
    Die Ergebnisse werden also in eine beliebige Struktur geschrieben, die beim anlegen des Jobs übergeben wird.

    Code:
    struct mystruct shared_data;
    jobstack_put(&func_ptr, (void *) &shared_data);
    Zitat Zitat von oberallgeier;
    static ?
    Wäre möglich, in meinen Augen aber unsauber da lokale Variablen dadurch Datei-Global sind.

    @witkatz: Deine Lösung ist wahrscheinlich die einfachste. Ich hab mir nur überlegt, ob man das ganze Switch-Case gedöns irgendwie Sinnvoll verstecken könnte.

Seite 1 von 3 123 LetzteLetzte

Ähnliche Themen

  1. Nach ISR in beliebige Funktion springen? Wie? Inline-Asm?
    Von Manu_91 im Forum C - Programmierung (GCC u.a.)
    Antworten: 15
    Letzter Beitrag: 17.09.2015, 09:56
  2. ein Int-Array einer Funktion
    Von oderlachs im Forum Arduino -Plattform
    Antworten: 13
    Letzter Beitrag: 17.02.2014, 23:50
  3. Stack beim verlassen einer Schleife...
    Von Klingon77 im Forum Software, Algorithmen und KI
    Antworten: 10
    Letzter Beitrag: 26.04.2009, 11:17
  4. Funktion gibt Funktion zurück... nächstes Problem
    Von Jaecko im Forum C - Programmierung (GCC u.a.)
    Antworten: 2
    Letzter Beitrag: 19.12.2008, 09:51
  5. Funktion als Rückgabewert einer Funktion?
    Von Jaecko im Forum C - Programmierung (GCC u.a.)
    Antworten: 1
    Letzter Beitrag: 08.09.2008, 11:25

Stichworte

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

12V Akku bauen