//$T sharedTimer.cpp GC 1.140 06/11/08 15:16:12 /*$6 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ #include #include "sharedTimer.h" #define QUEUESIZE 10 #define PARENT(i) ((i - 1) / 2) #define LEFT(i) ((2 * i + 1)) #define ABSOLUTETIME(n) (n.absoluteTime) typedef struct { unsigned long absoluteTime; unsigned int interval; funcp execute; } notification_t; typedef struct { notification_t heap[QUEUESIZE]; unsigned char count; } priorityQueue_t; void enqueue_notification(notification_t *n); notification_t *dequeue_notification(notification_t *item); notification_t *top_notification(notification_t *n); void bubbleUp(unsigned char index, notification_t *item); void trickleDown(unsigned char index, notification_t *item); priorityQueue_t queue; // priorisierte Queue unsigned long stTime; // Zeit des Timers /* =============================================================================== * Initialisiert den Timer =============================================================================== */ void shared_timer_init(unsigned long time) { queue.count = 0; stTime = time; } /* =============================================================================== * Timer ausfuehren =============================================================================== */ void shared_timer_tick(unsigned long time) { stTime = time; notification_t n; if (queue.count > 0) { n = *top_notification(&n); if (stTime >= n.absoluteTime) { n = *dequeue_notification(&n); n.absoluteTime = stTime + n.interval; n.execute(); if (n.interval != 0) { enqueue_notification(&n); } } } } /* =============================================================================== * Plant eine regelmaessige Benachrichtigung ein =============================================================================== */ void shared_timer_notifyEach(unsigned int seconds, funcp execute) { notification_t n; n.absoluteTime = stTime + seconds; n.interval = seconds; n.execute = execute; enqueue_notification(&n); } /* =============================================================================== * Plant eine Benachrichtigung zu einem absoluten Zeitpunkt ein =============================================================================== */ void shared_timer_notifyAt(unsigned int time, funcp execute) { notification_t n; n.absoluteTime = time; n.interval = 0; n.execute = execute; enqueue_notification(&n); } /* =============================================================================== * Plant eine Benachrichtigung ein =============================================================================== */ void enqueue_notification(notification_t *item) { ++queue.count; bubbleUp(queue.count - 1, item); } /* =============================================================================== * Benachrichtigung entfernen =============================================================================== */ notification_t *dequeue_notification(notification_t *item) { if (queue.count == 0) return NULL; *item = queue.heap[0]; --queue.count; trickleDown(0, &queue.heap[queue.count]); return item; } /* =============================================================================== * Oberste Benachrichtigung abrufen =============================================================================== */ notification_t *top_notification(notification_t *item) { if (queue.count == 0) return NULL; *item = queue.heap[0]; return item; } /* =============================================================================== * Benachrichtigung im Heap aufwaerts steigen lassen =============================================================================== */ void bubbleUp(unsigned char index, notification_t *item) { unsigned char parent = PARENT(index); // Note: (index > 0) means there is a parent while ((index > 0) && (ABSOLUTETIME(queue.heap[parent]) > item->absoluteTime)) { queue.heap[index] = queue.heap[parent]; index = parent; parent = PARENT(index); } queue.heap[index] = *item; } /* =============================================================================== * Benachrichtigung im Heap abwaerts steigen lassen =============================================================================== */ void trickleDown(unsigned char index, notification_t *item) { unsigned char child = LEFT(index); while (child < queue.count) { if( ((child + 1) < queue.count) && (ABSOLUTETIME(queue.heap[child]) > ABSOLUTETIME(queue.heap[child + 1])) ) { ++child; } queue.heap[index] = queue.heap[child]; index = child; child = LEFT(index); } bubbleUp(index, item); }