summaryrefslogtreecommitdiff
path: root/src/common/timer.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/common/timer.c')
-rw-r--r--src/common/timer.c320
1 files changed, 112 insertions, 208 deletions
diff --git a/src/common/timer.c b/src/common/timer.c
index fca6f42..f4be19b 100644
--- a/src/common/timer.c
+++ b/src/common/timer.c
@@ -1,184 +1,123 @@
-// $Id: timer.c,v 1.1.1.1 2004/09/10 17:44:49 MagicalTux Exp $
-// original : core.c 2003/02/26 18:03:12 Rev 1.7
-
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
-#ifdef LCCWIN32
-#include <winsock.h>
-#else
#include <sys/socket.h>
#include <sys/time.h>
-#endif
#include "timer.h"
#include "utils.h"
-#ifdef MEMWATCH
-#include "memwatch.h"
-#endif
-
static struct TimerData *timer_data;
-static int timer_data_max, timer_data_num;
-static int *free_timer_list;
-static int free_timer_list_max, free_timer_list_pos;
-
-static int timer_heap_max;
-static int *timer_heap = NULL;
-
-// for debug
-struct timer_func_list
-{
- int (*func) (int, unsigned int, int, int);
- struct timer_func_list *next;
- char *name;
-};
-static struct timer_func_list *tfl_root;
-
-#if defined(LCCWIN32)
-void gettimeofday (struct timeval *t, struct timezone *dummy)
-{
- DWORD millisec = GetTickCount ();
-
- t->tv_sec = (int) (millisec / 1000);
- t->tv_usec = (millisec % 1000) * 1000;
-}
-
-#endif
-
-//
-int add_timer_func_list (int (*func) (int, unsigned int, int, int),
- char *name)
-{
- struct timer_func_list *tfl;
-
- CREATE (tfl, struct timer_func_list, 1);
- CREATE (tfl->name, char, strlen (name) + 1);
-
- tfl->next = tfl_root;
- tfl->func = func;
- strcpy (tfl->name, name);
- tfl_root = tfl;
-
- return 0;
-}
-
-char *search_timer_func_list (int (*func) (int, unsigned int, int, int))
-{
- struct timer_func_list *tfl;
- for (tfl = tfl_root; tfl; tfl = tfl->next)
- {
- if (func == tfl->func)
- return tfl->name;
- }
- return "???";
-}
-
-/*----------------------------
- * Get tick time
- *----------------------------*/
-static unsigned int gettick_cache;
-static int gettick_count;
-unsigned int gettick_nocache (void)
+static uint32_t timer_data_max, timer_data_num;
+static timer_id *free_timer_list;
+static uint32_t free_timer_list_max, free_timer_list_pos;
+
+/// Okay, I think I understand this structure now:
+/// the timer heap is a magic queue that allows inserting timers and then popping them in order
+/// designed to copy only log2(N) entries instead of N
+// timer_heap[0] is the size (greatest index into the heap)
+// timer_heap[1] is the first actual element
+// timer_heap_max increases 256 at a time and never decreases
+static uint32_t timer_heap_max = 0;
+/// FIXME: refactor the code to put the size in a separate variable
+//nontrivial because indices get multiplied
+static timer_id *timer_heap = NULL;
+
+
+static uint32_t gettick_cache;
+static uint8_t gettick_count = 0;
+
+uint32_t gettick_nocache (void)
{
struct timeval tval;
+ // BUG: This will cause strange behavior if the system clock is changed!
+ // it should be reimplemented in terms of clock_gettime(CLOCK_MONOTONIC, )
gettimeofday (&tval, NULL);
- gettick_count = 256;
+ gettick_count = 255;
return gettick_cache = tval.tv_sec * 1000 + tval.tv_usec / 1000;
}
-unsigned int gettick (void)
+uint32_t gettick (void)
{
- gettick_count--;
- if (gettick_count < 0)
- return gettick_nocache ();
- return gettick_cache;
+ if (gettick_count--)
+ return gettick_cache;
+ return gettick_nocache ();
}
-/*======================================
- * CORE : Timer Heap
- *--------------------------------------
- */
-static void push_timer_heap (int index)
+static void push_timer_heap (timer_id index)
{
- int i, h;
-
if (timer_heap == NULL || timer_heap[0] + 1 >= timer_heap_max)
{
- int first = timer_heap == NULL;
-
timer_heap_max += 256;
RECREATE (timer_heap, int, timer_heap_max);
- memset (timer_heap + (timer_heap_max - 256), 0, sizeof (int) * 256);
- if (first)
- timer_heap[0] = 0;
+ memset (timer_heap + (timer_heap_max - 256), 0, sizeof (timer_id) * 256);
}
-
+// timer_heap[0] is the greatest index into the heap, which increases
timer_heap[0]++;
- for (h = timer_heap[0] - 1, i = (h - 1) / 2;
- h > 0 && DIFF_TICK (timer_data[index].tick,
- timer_data[timer_heap[i + 1]].tick) < 0;
- i = (h - 1) / 2)
+ timer_id h = timer_heap[0]-1, i = (h - 1) / 2;
+ while (h)
{
+ // avoid wraparound problems, it really means this:
+ // timer_data[index].tick >= timer_data[timer_heap[i+1]].tick
+ if ( DIFF_TICK(timer_data[index].tick, timer_data[timer_heap[i+1]].tick) >= 0)
+ break;
timer_heap[h + 1] = timer_heap[i + 1];
h = i;
+ i = (h - 1) / 2;
}
timer_heap[h + 1] = index;
}
-static int top_timer_heap ()
+static timer_id top_timer_heap ()
{
- if (timer_heap == NULL || timer_heap[0] <= 0)
+ if (!timer_heap || !timer_heap[0])
return -1;
-
return timer_heap[1];
}
-static int pop_timer_heap ()
+static timer_id pop_timer_heap ()
{
- int i, h, k;
- int ret, last;
-
- if (timer_heap == NULL || timer_heap[0] <= 0)
+ if (!timer_heap || !timer_heap[0])
return -1;
- ret = timer_heap[1];
- last = timer_heap[timer_heap[0]];
+ timer_id ret = timer_heap[1];
+ timer_id last = timer_heap[timer_heap[0]];
timer_heap[0]--;
+ uint32_t h, k;
for (h = 0, k = 2; k < timer_heap[0]; k = k * 2 + 2)
{
- if (DIFF_TICK
- (timer_data[timer_heap[k + 1]].tick,
- timer_data[timer_heap[k]].tick) > 0)
+ if (DIFF_TICK(timer_data[timer_heap[k + 1]].tick, timer_data[timer_heap[k]].tick) > 0)
k--;
timer_heap[h + 1] = timer_heap[k + 1], h = k;
}
if (k == timer_heap[0])
timer_heap[h + 1] = timer_heap[k], h = k - 1;
- for (i = (h - 1) / 2;
- h > 0
- && DIFF_TICK (timer_data[timer_heap[i + 1]].tick,
- timer_data[last].tick) > 0; i = (h - 1) / 2)
+ uint32_t i = (h - 1) / 2;
+ while (h)
{
- timer_heap[h + 1] = timer_heap[i + 1], h = i;
+ if (DIFF_TICK (timer_data[timer_heap[i + 1]].tick, timer_data[last].tick) <= 0)
+ break;
+ timer_heap[h + 1] = timer_heap[i + 1];
+ h = i;
+ i = (h - 1) / 2;
}
timer_heap[h + 1] = last;
return ret;
}
-int add_timer (unsigned int tick, int (*func) (int, unsigned int, int, int),
- int id, int data)
+timer_id add_timer (tick_t tick, timer_func func, custom_id_t id, custom_data_t data)
{
- struct TimerData *td;
- int i;
+ timer_id i;
if (free_timer_list_pos)
{
+ // Retrieve a freed timer id instead of a new one
+ // I think it should be possible to avoid the loop somehow
do
{
i = free_timer_list[--free_timer_list_pos];
@@ -187,12 +126,13 @@ int add_timer (unsigned int tick, int (*func) (int, unsigned int, int, int),
}
else
i = timer_data_num;
+
+ // I have no idea what this is doing
if (i >= timer_data_num)
- for (i = timer_data_num; i < timer_data_max && timer_data[i].type;
- i++);
+ for (i = timer_data_num; i < timer_data_max && timer_data[i].type; i++)
+ ;
if (i >= timer_data_num && i >= timer_data_max)
{
- int j;
if (timer_data_max == 0)
{
timer_data_max = 256;
@@ -202,143 +142,112 @@ int add_timer (unsigned int tick, int (*func) (int, unsigned int, int, int),
{
timer_data_max += 256;
RECREATE (timer_data, struct TimerData, timer_data_max);
- if (timer_data == NULL)
- {
- printf ("out of memory : add_timer timer_data\n");
- exit (1);
- }
memset (timer_data + (timer_data_max - 256), 0,
sizeof (struct TimerData) * 256);
}
- for (j = timer_data_max - 256; j < timer_data_max; j++)
- timer_data[j].type = 0;
}
- td = &timer_data[i];
- td->tick = tick;
- td->func = func;
- td->id = id;
- td->data = data;
- td->type = TIMER_ONCE_AUTODEL;
- td->interval = 1000;
+ timer_data[i].tick = tick;
+ timer_data[i].func = func;
+ timer_data[i].id = id;
+ timer_data[i].data = data;
+ timer_data[i].type = TIMER_ONCE_AUTODEL;
+ timer_data[i].interval = 1000;
push_timer_heap (i);
if (i >= timer_data_num)
timer_data_num = i + 1;
return i;
}
-int add_timer_interval (unsigned int tick,
- int (*func) (int, unsigned int, int, int), int id,
- int data, int interval)
+timer_id add_timer_interval (tick_t tick, timer_func func, custom_id_t id,
+ custom_data_t data, interval_t interval)
{
- int tid;
- tid = add_timer (tick, func, id, data);
+ timer_id tid = add_timer (tick, func, id, data);
timer_data[tid].type = TIMER_INTERVAL;
timer_data[tid].interval = interval;
return tid;
}
-int delete_timer (int id, int (*func) (int, unsigned int, int, int))
+void delete_timer (timer_id id, timer_func func)
{
- if (id <= 0 || id >= timer_data_num)
+ if (id == 0 || id >= timer_data_num)
{
- printf ("delete_timer error : no such timer %d\n", id);
- return -1;
+ fprintf (stderr, "delete_timer error : no such timer %d\n", id);
+ abort ();
}
if (timer_data[id].func != func)
{
- printf
- ("delete_timer error : function dismatch %08x(%s) != %08x(%s)\n",
- (int) timer_data[id].func,
- search_timer_func_list (timer_data[id].func), (int) func,
- search_timer_func_list (func));
- return -2;
+ fprintf (stderr, "Timer mismatch\n");
+ abort ();
}
- // そのうち消えるにまかせる
+ // "to let them disappear" - is this just in case?
timer_data[id].func = NULL;
timer_data[id].type = TIMER_ONCE_AUTODEL;
timer_data[id].tick -= 60 * 60 * 1000;
- return 0;
}
-int addtick_timer (int tid, unsigned int tick)
+tick_t addtick_timer (timer_id tid, interval_t tick)
{
return timer_data[tid].tick += tick;
}
-struct TimerData *get_timer (int tid)
+struct TimerData *get_timer (timer_id tid)
{
return &timer_data[tid];
}
-int do_timer (unsigned int tick)
+interval_t do_timer (tick_t tick)
{
- int i, nextmin = 1000;
-
-#if 0
- static int disp_tick = 0;
- if (DIFF_TICK (disp_tick, tick) < -5000
- || DIFF_TICK (disp_tick, tick) > 5000)
- {
- printf ("timer %d(%d + %d)\n", timer_data_num, timer_heap[0],
- free_timer_list_pos);
- disp_tick = tick;
- }
-#endif
+ timer_id i;
+ /// Number of milliseconds until it calls this again
+ // this says to wait 1 sec if all timers get popped
+ interval_t nextmin = 1000;
- while ((i = top_timer_heap ()) >= 0)
+ while ((i = top_timer_heap ()) != (timer_id)-1)
{
+ // while the heap is not empty and
if (DIFF_TICK (timer_data[i].tick, tick) > 0)
{
+ /// Return the time until the next timer needs to goes off
nextmin = DIFF_TICK (timer_data[i].tick, tick);
break;
}
pop_timer_heap ();
- timer_data[i].type |= TIMER_REMOVE_HEAP;
if (timer_data[i].func)
{
if (DIFF_TICK (timer_data[i].tick, tick) < -1000)
{
- // 1秒以上の大幅な遅延が発生しているので、
- // timer処理タイミングを現在値とする事で
- // 呼び出し時タイミング(引数のtick)相対で処理してる
- // timer関数の次回処理タイミングを遅らせる
- timer_data[i].func (i, tick, timer_data[i].id,
- timer_data[i].data);
+ // If we are too far past the requested tick, call with the current tick instead to fix reregistering problems
+ timer_data[i].func (i, tick, timer_data[i].id, timer_data[i].data);
}
else
{
- timer_data[i].func (i, timer_data[i].tick, timer_data[i].id,
- timer_data[i].data);
+ timer_data[i].func (i, timer_data[i].tick, timer_data[i].id, timer_data[i].data);
}
}
- if (timer_data[i].type & TIMER_REMOVE_HEAP)
+ switch (timer_data[i].type)
{
- switch (timer_data[i].type & ~TIMER_REMOVE_HEAP)
- {
- case TIMER_ONCE_AUTODEL:
- timer_data[i].type = 0;
- if (free_timer_list_pos >= free_timer_list_max)
- {
- free_timer_list_max += 256;
- RECREATE (free_timer_list, int, free_timer_list_max);
- memset (free_timer_list + (free_timer_list_max - 256),
- 0, 256 * sizeof (free_timer_list[0]));
- }
- free_timer_list[free_timer_list_pos++] = i;
- break;
- case TIMER_INTERVAL:
- if (DIFF_TICK (timer_data[i].tick, tick) < -1000)
- {
- timer_data[i].tick = tick + timer_data[i].interval;
- }
- else
- {
- timer_data[i].tick += timer_data[i].interval;
- }
- timer_data[i].type &= ~TIMER_REMOVE_HEAP;
- push_timer_heap (i);
- break;
- }
+ case TIMER_ONCE_AUTODEL:
+ timer_data[i].type = 0;
+ if (free_timer_list_pos >= free_timer_list_max)
+ {
+ free_timer_list_max += 256;
+ RECREATE (free_timer_list, uint32_t, free_timer_list_max);
+ memset (free_timer_list + (free_timer_list_max - 256),
+ 0, 256 * sizeof (uint32_t));
+ }
+ free_timer_list[free_timer_list_pos++] = i;
+ break;
+ case TIMER_INTERVAL:
+ if (DIFF_TICK (timer_data[i].tick, tick) < -1000)
+ {
+ timer_data[i].tick = tick + timer_data[i].interval;
+ }
+ else
+ {
+ timer_data[i].tick += timer_data[i].interval;
+ }
+ push_timer_heap (i);
+ break;
}
}
@@ -346,8 +255,3 @@ int do_timer (unsigned int tick)
nextmin = 10;
return nextmin;
}
-
-void timer_final ()
-{
- free (timer_data);
-}