Leopold Toetsch wrote:
> Attached is a test program, showing an implementations for multiple
> timers. GNU/linux only, but implementing the platform interface (and the
> sighandler/message queue) shouldn't be too hard.
don't know if it's worth something, but this is how your timer program
could look like under Win32.
rename timer_win32_c.txt to timer_win32.c and compile with:
cl timer_win32.c /link user32.lib
I had to comment out the signal(SIGALRM, sig_alarm_handler); line and
add a PeekMessage/DispatchMessage routine in the while loop.
the rest of the Win32-specific code is in the "platform interface"
section.
I realize this is really ugly, but Win32 doesn't seem to have support
for alarms, so you have to relay on windows messages instead. if
someone can come up with a better way to do it, I'm really curious to
see it :-)
cheers,
Aldo
__END__
$_=q,just perl,,s, , another ,,s,$, hacker,,print;
/*
* itimer test
*/
/* #include <sys/time.h> */
#include <windows.h>
#include <signal.h>
#include <stdio.h>
#include <malloc.h>
#include <math.h>
volatile sig_atomic_t got_alarm = 0;
typedef struct timer_t {
int ticks;
int value;
int repeat;
int run;
int nr;
struct timer_t *next;
struct timer_t *prev;
} timer;
timer *rtimer = 0;
void add_timer(timer *t) {
timer *next = rtimer;
rtimer = t;
t->next = next;
if (next) {
t->nr = next->nr + 1;
next->prev = t;
}
else
t->nr = 1;
}
void del_timer(timer *t) {
timer *next = t->next;
timer *prev = t->prev;
if (prev)
prev->next = next;
else
rtimer = next;
if (next)
next->prev = prev;
free(t);
}
timer * new_timer(void) {
timer *t = calloc(1, sizeof(timer));
add_timer(t);
return t;
}
typedef unsigned int UINTVAL;
typedef double FLOATVAL;
UINTVAL gcd(UINTVAL a, UINTVAL b) {
UINTVAL q = 0;
UINTVAL c = 0;
while (b != 0) {
q = (UINTVAL)floor( (FLOATVAL)a/b );
c = a - b*q;
a = b;
b = c;
}
return a;
}
void
sig_alarm_handler(int i) {
got_alarm = 1;
}
/* platform interface */
typedef struct win32_timer_t {
UINT_PTR id;
UINT ms;
} win32_timer;
VOID CALLBACK proc_sys_timer_ms(
HWND hwnd,
UINT uMsg,
UINT_PTR idEvent,
DWORD dwTime
) {
got_alarm = 1;
}
void start_sys_timer_ms(void *handle, int ms) {
win32_timer * t = (win32_timer *) handle;
t->id = SetTimer(NULL, 0, ms, proc_sys_timer_ms);
t->ms = ms;
printf("new ms = %d\n",
ms);
}
void stop_sys_timer_ms(void *handle) {
win32_timer * t = (win32_timer *) handle;
KillTimer(NULL, t->id);
free(t);
}
int get_sys_timer_ms(void *handle) {
win32_timer * t = (win32_timer *) handle;
return t->ms;
}
void * new_sys_timer_ms() {
win32_timer *t = calloc(1, sizeof(win32_timer));
t->ms = 0;
t->id = (UINT_PTR) NULL;
return (void *) t;
}
/* end platform interface */
void recalc_ticks(void);
void *handle;
void
do_alarm_handler() {
timer *t;
UINTVAL ms;
int recalc = 0;
ms = get_sys_timer_ms(handle);
for (t = rtimer; t; t= t->next) {
if (!--t->ticks) {
t->run = 1;
if (t->repeat) {
t->ticks = t->value/ms;
if (t->repeat != -1)
t->repeat--;
}
}
}
again:
for (t = rtimer; t; t= t->next) {
if (t->run == 1) {
t->run = 0;
printf("alarm %d\n", t->nr);
/* code run here may add timers, these have t->run = 2 */
goto again;
}
if (!t->ticks && !t->repeat) {
printf("del_timer %d\n", t->nr);
del_timer(t);
recalc = 1;
goto again;
}
}
if (recalc)
recalc_ticks();
}
void p_add_timer(UINTVAL msecs, int repeat)
{
timer *t;
if (!msecs)
return;
t = new_timer();
t->repeat = repeat;
t->value = msecs;
t->run = 2;
recalc_ticks();
}
void p_del_timer(timer *t) {
del_timer(t);
recalc_ticks();
}
void recalc_ticks() {
UINTVAL ms, oms;
timer *t;
oms = get_sys_timer_ms(handle);
printf("gettimer oms = %d\n", oms);
t = rtimer;
if (t) {
t->run = 0;
if (oms && t->ticks)
ms = oms*t->ticks; /* time left */
else
ms = t->value;
if (t->next) {
for (t = t->next; t; t = t->next) {
t->run = 0;
if (oms && t->ticks) {
ms = gcd(oms*t->ticks, ms);
}
else
ms = gcd(t->value, ms);
}
}
printf("new ms %d\n", ms);
again:
for (t = rtimer; t; t= t->next) {
int ot = t->ticks;
printf("t%d oticks %d => ", t->nr, t->ticks);
if (oms && ot)
t->ticks = t->ticks * ((double)oms / (double)ms);
else
t->ticks = t->value / ms;
if (!t->ticks) {
ms = oms;
t->ticks = ot;
goto again;
}
printf("ticks %d value %d\n", t->ticks, t->value);
}
}
else
ms = 0;
if (ms)
start_sys_timer_ms(handle, ms);
else
stop_sys_timer_ms(handle);
}
int main(int argc, char **argv) {
MSG msg = { 0, 0, 0, 0 };
handle = new_sys_timer_ms();
/* signal(SIGALRM, sig_alarm_handler); */
p_add_timer(3000, 1);
p_add_timer(2000, 3);
p_add_timer(500, 1);
while (rtimer) {
if (got_alarm) { /* CHECK_EVENTS */
got_alarm = 0;
do_alarm_handler();
}
if (PeekMessage(&msg, 0, WM_TIMER, WM_TIMER, PM_REMOVE) ) {
DispatchMessage(&msg);
}
}
return 0;
}