Forum: Projekte & Code Shared Timer


von BPDI (Gast)


Angehängte Dateien:

Lesenswert?

Dieses Modul dient zur gemeinsamen Nutzung eines Timers.

Im wesentlichen besteht der SharedTimer aus einer priorisierten Queue 
von Benachrichtigungs-Elementen, die aufsteigen nach dem jeweiligen 
Auslösezeitpunkt sortiert werden.

Daraus ergibt sich das in der Regel nur der Auslösezeitpunkt der oberste 
Benachrichtigung überprüft werden muss, ist dieser erreicht oder wurde 
er bereits überschritten, wird die Benachrichtigung aus der Queue 
abgerufen und die übergebene Funktion ausgeführt.

Über die Methode shared_timer_init(...) wird das Modul initialisiert.

Die Methode shared_timer_tick(...) muss regelmäßig durchlaufen werden, 
denn hier findet die Überprüfung und Auslösung der eingestellten 
Benachrichtigungen statt. Über den Parameter time wird die aktuelle 
Systemzeit übergeben, diese wird zum Zeitvergleich mit den 
Auslösezeitpunkten der Benachrichtigungen benötigt.

Über die Methoden shared_timer_notifyEach(...), 
shared_timer_notifyAt(...) können Benachrichtigungen eingestellt werden. 
Über shared_timer_notifyEach(...) kann eine regelmäßige Benachrichtigung 
eingestellt werden, über den Parameter seconds wird das Interval der 
Benachrichtigung angegeben. Über shared_timer_notifyAt(...) wird eine 
einmalige Benachrichtiung eingestellt, der Parameter time legt den 
Auslösezeitpunkt fest.

Im aktuellen Versionsstand verwende ich eine Variable vom Typ unsigned 
long welche die fortlaufende Systemzeit hält. Und in meier aktuellen 
Anwendung des SharedTimers wird diese Systemzeit im Sekundentakt 
hochgezählt.

Da ich mit meinen C Kenntnissen nach am Anfang stehe bitte ich euch 
einmal den Code zu beurteilen.

von Wasweissich (Gast)


Lesenswert?

Ich muss schon sagen, das Du Dir augenscheinlich viel Mühe gemacht hast 
gut zu strukturieren. Und das Ganze ist sicherlich nach einigen 
Verbesserungen gut brauchbar.

Dennoch gibt es ja immer etwas zu verbessern. Vielleicht überdenkst Du 
die folgenden Punkte und entscheidest Dich dann ob Du meine Kritik 
zutreffend findest.

1. Namenswahl
An verschiedenen Stellen finde ich Namen von Variablen, Funktionen und 
Makros die mir nicht passend erscheinen.

Zuerst möchte ich aber vorausschicken, dass mir hier "enqueue" und 
"dequeue" zutreffend zu sein scheint. Denn dies ist ja fast der Prototyp 
einer Warteschlange.

1.a. LEFT, PARENT
Als ich das gelesen habe, habe ich ganz instinktiv nochmal in die 
Definition der Struktur geguckt, ob ich darin Zeiger auf linke oder 
Rechte Knoten finde. Die Terminologie kenne ich von Bäumen. Es handelt 
sich hier aber nicht um Bäume. Da die einzelnen Einträge keinen 
Zusammenhang haben, es handelt sich um unabhängig voneinander laufende 
"Timer" haben die keinen linken Nachfolger oder einen Parent 
(Elternteil).
Auch die andere mögliche Bedeutung von "LEFT", nämlich "verbleibend" 
oder etwas unschärfer "Rest" scheint mir hier nicht zuzutreffen.
Die Berechnung in LEFT und PARENT scheint mir eher auf ein binäres 
Sortieren als auf BubbleSort hinzuweisen.

1.b. Heap
"Heap" heisst ja Haufen. Eine ungeordnete Menge von Dingen. Da hier aber 
eine Array (schon aus der Deklaration erkennbar) vorliegt und auch die 
Elemente geordnet sind scheint mir das nicht passend. Ausserdem hat das 
Wort Heap schon zwei Verwendungen. In dem nämlich dies ein Bereich von 
Speicher ist, von dem zur Laufzeit eines Programmes Variablen 
angefordert werden (malloc, free) oder auch eine Baumstruktur gemeint 
ist. (Siehe Wikipedia).

2. Als zweites sind mir einige Punkt bei der Programmierung aufgefallen:

2.a. In dequeue_notification prüfst Du als erstes ob in dem Array der 
Timer noch welche vorhanden sind. Das aber ist in shared_timer_tick 
schon die Vorbedingung zum Aufruf von dequeue_notification. Es braucht 
also nicht noch ein zweites Mal aufgerufen werden.

2.b. Was mir merkwürdig vorkommt, ist das ein abgelaufener Timer durch 
dequeue_notification behandelt werden muss. Er könnte doch einfach 
gelöscht werden.

2.c. In dem Zusammenhang ist es besser zu prüfen ob ein Timer in der 
Liste verbleiben muss (bei einem zyklischen Timer) bevor man das ganze 
dequeue_notification und enqueue_notification laufen lässt.

2.d. Das Ganze könnte etwas einfach sein, wenn man einen Ringbuffer 
verwendet.

2.e. Das Programm prüft nicht ob noch weitere Timer mit der gleichen 
Ablaufzeit vorliegen. Ein evtl. weiterer Timer würde dann erst eine 
Sekunde später ablaufen. Ein folgender mit der gleichen Ablaufzeit 
wiederum eine Sekunde später.

2.f. Das Programm könnte universeller (und schneller sein), wenn nicht 
die absolute Zeit des Ablaufens sondern die Anzahl der Sekunden _bis zum 
ablaufen_ gespeichert wird. Die Variable könnte dann kleiner sein und 
die Verarbeitung wäre schneller.


Ich hoffe Du findest die Kritik hilfreich.

Gruss

von BPDI (Gast)


Lesenswert?

Hallo

Vielen Dank für Die Hinweise, Kritik. Werde versuchen an Hand der 
Vorschläge das ganze noch einmal zu überarbeiten.

von Ralf S. (spacedog) Benutzerseite


Lesenswert?

@Wasweissich, zu Punkt 1.a/b.:

Mensch, nur weil du nicht verstehst, was BPDI gemacht hat, heisst noch 
lange nicht, dass eine Heap-Struktur nicht geeignet ist. Das ganze 
implementiert halt einen Heap-Sort, welcher es ermöglicht, dass man in 
ca. O(log(n)) Zeit Daten hineinschreiben kann und auch in O(log(n)) 
Daten herauslesen kann. Die Zeit zur Sortierung der Timer-Ereignisse 
wird somit gerecht verteilt zwischen dem Zeitpunkt wo ein neues Ereignis 
in die Queue kommt und dem Zeitpunkt wo das nächste Ereignis eintrifft. 
Dies kann in vielen Fällen sehr sinnvoll sein. Lern also erst mal 
Programmieren, Wasweissich.


@BPDI:

Wirklich super. Dass du mit deinen C-Kenntnissen noch am Anfang stehst 
macht ja nichts, denn du kennst dich aus mit Datenstrukturen und 
Algorithmen. Ich hoffe dich noch oft hier anzutreffen im Forum, solche 
Leute wie dich kann man brauchen. Denn leider hat es viele Besserwisser 
hier und manchmal etwas zu wenig solche die wirklich verstehen, worüber 
sie reden.

von Peter D. (peda)


Lesenswert?

Ralf Schwarz wrote:

> Lern also erst mal
> Programmieren, Wasweissich.


Was ist denn mit Dir los?

Na klar, das hier ist ein Forum nur für die Super-Gurus, alle anderen 
haben gefälligst die Klappe zu halten.
Es liegt in der Natur des Menschen, daß man nicht alles versteht, dann 
kannst Du das doch vernünftig sagen und erklären.

Z.B. die Idee mit der Differenzzeit statt der absoluten Zeit ist nicht 
nur Ressourcen sparender, sondern macht auch keine Fehler beim 
Timerüberlauf.
O.k. bei 1ms Zeitbasis tritt der Überlauf nur alle 50 Tage auf, aber 
Fehler bleibt Fehler.
Und wenn alle 50 Tage die Bestrahlzeit eines medizinischen Gerätes 
falsch ist, dann entschuldige Dich bitte Du dafür bei den 
Hinterbliebenen.


Peter

von Peter D. (peda)


Lesenswert?

Ralf Schwarz wrote:

> @BPDI:
>
> Wirklich super. Dass du mit deinen C-Kenntnissen noch am Anfang stehst
> macht ja nichts

Also ehrlich gesagt, auf mich wirkt der Code definitiv nicht wie der 
eines Anfängers.
Die Benutzung von Macros und Pointern ist nicht der typische 
Anfängerstil.
Das Programm sieht einfach zu elegant aus für einen Anfänger.


Peter

von BPDI (Gast)


Lesenswert?

Hallo

Grundlage zum Thema priorisierte Warteschlangen findet man auch unter 
Wikipedia. Vorlage oder auch Muster für meinen Code, war eine Lösung die 
schon einmal unter VB6 entstanden ist. Ein paar Lösungen in der 
Programmiersprache C findet man auch im Netz, wo auch Macros angewendet 
wurden.
Als Anfänger möchte man natürlich irgendwann mal ein Ergebnis erreichen 
und verwendet Code aus Beispielen, die man unter Umständen noch nicht 
vollständig verstanden hat. So entsteht dann Code der zwar in einem 
gewissen Kontext funktioniert, aber unter Betrachtung von Code Sytle, 
Bennungskonventionen, Ressourcenverbrauch nicht sauber ist. Und die 
Pointer Problematik ist für Anfänger auch eine Hürde die zu 
Unsicherheiten führt.

Zu den Punkten:

>2.e. Das Programm prüft nicht ob noch weitere Timer mit der gleichen
>Ablaufzeit vorliegen. Ein evtl. weiterer Timer würde dann erst eine
>Sekunde später ablaufen. Ein folgender mit der gleichen Ablaufzeit
>wiederum eine Sekunde später.

In meiner Anwendung ist die verzögerter Auslösunge von Timern mit 
gleicher Ablaufzeit nicht kritisch, daher habe ich immer nur das oberste 
Benachrichtigungselement überprüft.

Die Lösung mit der Differenzzeit von Benachrichtigungselement zu 
Benachrichtigungselement ist sicherlich ein bessere Weg und auch 
Ressourcen schonender.

von Wasweissich (Gast)


Lesenswert?

@ Ralf Schwarz

Deinen Kommentar hättest Du auch freundlicher formulieren können.

Mag ja sein, das ich nicht erkannt habe, das hier HeapSort angewendet 
worden ist, aber ist das ein Grund mich dermassen anzugreifen und 
abzuqualifizieren? Machst Du nie Fehler?

Wenn ich programmieren lernen muss musst Du erstmal soziales Verhalten 
lernen.

von Wasweissich (Gast)


Lesenswert?

Im übrigen fällt mir noch ein,
das die Timer ja eigentlich immer sortiert sind,
wenn ein neuer Timer eingetragen wird.
(Nicht gleich in der Luft zerreissen,
wenn das nicht zutrifft).
Vielleicht würde dann eine BinarySort ausreichen.

von Wasweissich (Gast)


Lesenswert?

Ich schrieb:
>Vielleicht würde dann eine BinarySort ausreichen.
Haben beide die selbe Komplexität. Naja.
Hoffentlich liest Ralf Schwarz das nicht.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.