Timer Event



  • Hallo zusammen,

    ich habe mir eine TimerEventQueue implementiert, als doppelt verkette Liste.
    Hier die Struktur:

    typedef void (*TEFUNC)(void);
    
    typedef struct _TIMER_HEADER {
      struct _TIMER_HEADER	*nextEvent;
      struct _TIMER_HEADER	*prevEvent;
    }TIMER_HEADER;
    
    typedef struct _TIMER_EVENT {
      TIMER_HEADER	tHeader;
      BYTE		event;
      UINT32	timeout;
      UINT32	initTimeout;
      TEFUNC	eFunc;
    }TIMER_EVENT;
    

    Wobei tHeader Zeiger für das nächste und das vorhergehende Event hält.
    Die variable timeout gibt an in welchen Zyklus das Event auftreten soll.
    Als Zeitgeber hab ich einen Timer aufgezogen der die variable timeout dekrementiert und falls sie Null ist ruft die Timer-Isr die Funktion eFunc auf.

    Nun zu meiner Frage:
    Wie kann ich es machen, dass die Funktion eFunc als Übergabeparameter einen Zeiger auf die Struktur (TIMER_EVENT) selbst bekommt, so dass ich in der Funktion eFunc auf die Variablen (event, timeout usw.) zugreifen kann.

    Bsp:

    void vSetEstLocEvent(TIMER_EVENT* tEvent) {
    
     tEvent->event = ...;
     tEvent->timout = ...;
     usw.
    }
    
    int main(void) {
    
     //Parameter: event, timeout, eFunc
     xCreateTimerEvent(E_EST_LOC, GPRS_EST_LOC_INT, vSetEstLocEvent);
     for(;;);
    }
    

    Hoffe ich habe das einigermaßen verständlich machen können.

    Gruß, mdoemli



  • Hallo,

    ich habe deinen Beitrag noch nicht so ganz verstanden, aber ich schreibe
    hier mal auf, was mir so aufgefallen ist.

    Dein TIMER_HEADER enthält lediglich Zeiger auf next und prev TIMER_HEADER.
    Was ich hier aber vermisse ist das Object TIMER_EVENT selbst.
    Mit den Strukturen die du angegeben hast, kannst du keine TIMER_EVENTs in
    einer doppelt verketteten Liste verwalten.

    Hier mal ein Vorschlag von mir:

    typedef struct _TIMER_EVENT {
        BYTE   event;
        UINT32 timeout;
        UINT32 initTimeout;
        TEFUNC efunc;
    } TIMER_EVENT;
    
    typedef struct _TIMER_HEADER {
        struct _TIMER_HEADER   *next;
        struct _TIMER_HEADER   *prev;
        TIMER_EVENT            *event;  // oder das Object direkt
    } TIMER_EVENT_LIST;
    

    Die Benutzung wäre dann wie folgt:

    TIMER_EVENT_LIST *liste = NULL;
    
    TIMER_EVENT *event = new_timer_event(...);
    if (!liste) liste = create_new_timer_liste(event);
    else add_event(liste, event);
    

    Alternativ könntest du natürlich die Members des Structs TIMER_EVENT_LIST
    in TIMER_EVENT direkt speichern.

    Wenn ich dich richtig verstanden habe, wolltest du der Funktion efunc eines
    TIMER_EVENT das Object selber mitgeben.

    Dafür würde ich den Typ ändern:

    typedef void (*TEFUNC)(TIMER_EVENT*);
    

    Der Aufruf wäre dann wie folgt:
    Angenommen wir haben ein Object vom Typ TIMER_EVENT: timer_event

    void f(TIMER_EVENT *timer_event) {
        if (!timer_event) return;
        timer_event->efunc(timer_event);
    }
    

    Ich hoffe, ich konnte dir damit weiterhelfen.

    Gruß mcr



  • Hallo mcr,

    erstmal danke für den ausführlichen Beitrag.

    Mit den Strukturen die du angegeben hast, kannst du keine TIMER_EVENTs in
    einer doppelt verketteten Liste verwalten.

    Doch kann ich schon, da jedes TIMER_EVENT einen TIMER_HEADER enthält.
    Also das Aus- und Einhängen usw. funktioniert schon.

    So, jetzt hab ich was nicht ganz verstanden.
    Wenn du den Funktionszeiger als Übergabeparameter ein Objekt vom Typ TIMER_EVENT geben würdest würde der Compiler meckern.

    typedef void (*TEFUNC)(TIMER_EVENT*);
    
    typedef struct _TIMER_EVENT {
        BYTE   event;
        UINT32 timeout;
        UINT32 initTimeout;
        TEFUNC efunc;
    } TIMER_EVENT;
    
    typedef struct _TIMER_HEADER {
        struct _TIMER_HEADER   *next;
        struct _TIMER_HEADER   *prev;
        TIMER_EVENT            *event;  // oder das Object direkt
    } TIMER_EVENT_LIST;
    

    Denn zu diesem Zeitpunkt kennt er den Typ TIMER_EVENT noch nicht. Würde man die Definition vom Funktionszeiger unterhalb der Struktur angeben, so würde er meckern das er den Typ TEFUNC noch nicht kennt.

    Gruß, mdoemli



  • struct _TIMER_EVENT;
    
    typedef void (*TEFUNC)(struct _TIMER_EVENT*);
    
    typedef struct _TIMER_EVENT {
        BYTE   event;
        UINT32 timeout;
        UINT32 initTimeout;
        TEFUNC efunc;
    } TIMER_EVENT;
    
    typedef struct _TIMER_HEADER {
        struct _TIMER_HEADER   *next;
        struct _TIMER_HEADER   *prev;
        TIMER_EVENT            *event;  // oder das Object direkt
    } TIMER_EVENT_LIST;
    

    🙂



  • Mhhh, ok 🙄
    Merci!!!!! Manchmal steht man einfach aufn Schlauch. 😃

    Gruß, mdoemli



  • Als zweite Alternative kannst du den Typedef auch vorziehen:

    typedef struct _TIMER_EVENT TIMER_EVENT;
    
    typedef void (*TEFUNC)(TIMER_EVENT*);
    
    struct _TIMER_EVENT {
        BYTE   event;
        UINT32 timeout;
        UINT32 initTimeout;
        TEFUNC efunc;
    };
    
    typedef struct _TIMER_HEADER {
        struct _TIMER_HEADER   *next;
        struct _TIMER_HEADER   *prev;
        TIMER_EVENT            *event;  // oder das Object direkt
    } TIMER_EVENT_LIST;
    

    Zum ersteren: stimmt, du hast Recht, das Einhängen funktioniert.
    Ich hatte da einen Denkfehler.

    Gruß mcr



  • Hallo mcr,

    klingt auch gut! Werd auf jeden Fall das TIMER_EVENT Objekt in die Struktur TIMER_HEADER einbauen, dann spare ich mir einige Casts.
    Wünsch euch n schönes Wochenende und nochmals DANKE!

    Gruß, mdoemli


Log in to reply