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.
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
Hallo Vielen Dank für Die Hinweise, Kritik. Werde versuchen an Hand der Vorschläge das ganze noch einmal zu überarbeiten.
@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.
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
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
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.
@ 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.
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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.