/* * alarm.c * * Calling routines at set times * * © 1994-1998 Straylight */ /*----- Licensing note ----------------------------------------------------* * * This file is part of Straylight's Steel library. * * Steel is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * Steel is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Steel. If not, write to the Free Software Foundation, * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "alarm.h" #include "mem.h" #include "werr.h" #include "msgs.h" #include "os.h" #include "swiv.h" #include "swis.h" typedef struct alarm__str { struct alarm__str *next; alarm_handler proc; void *handle; int time; } alarm__str; static alarm__str *alarm__all; /* * void alarm_init(void) * * Use * None at all */ void alarm_init(void) { /* Hmmm.... this *is* an interesting function */ } /* * int alarm_timenow(void) * * Use * Reports the time right now */ int alarm_timenow(void) { return (_swi(OS_ReadMonotonicTime,_return(0))); } /* * int alarm_timedifference(int t1,int t2) * * Use * Tells you the difference between two times. t2 is considered to be later * than t1. */ int alarm_timedifference(int t1,int t2) { /* --- Humm.... How to deal with wraparound --- * * * Answer: Ignore it and subtract -- mod 2^32 arithmetic + 2s complement * sorts it all out for you. */ return (t2-t1); } /* * void alarm_set(int at,alarm_handler proc,void *handle) * * Use * Sets up `proc' to be called at time `at', being passed `handle'. */ void alarm_set(int at,alarm_handler proc,void *handle) { alarm__str *a=mem_alloc(sizeof(alarm__str)); alarm__str *p; if (!a) werr(FALSE,msgs_lookup("alarmNEM:Not enough memory for alarm")); else { /* --- Fill in the structure --- */ a->time=at; a->proc=proc; a->handle=handle; /* --- Scan the list and put the new node in the right place --- * * * Is this the right condition for the times? */ p=(alarm__str *)&alarm__all; while (p->next && p->next->timenext; a->next=p->next; p->next=a; } } /* * void alarm_remove(int at,void *handle) * * Use * Removes an alarm identified by a time and a handle */ void alarm_remove(int at,void *handle) { alarm__str *p; alarm__str *q; p=(alarm__str *)&alarm__all; while (p->next) { if (p->next->time==at && p->next->handle==handle) { q=p->next; p->next=q->next; mem_free(q); return; } p=p->next; } } /* * void alarm_removeall(void *handle) * * Use * Removes all alarms for the given handle */ void alarm_removeall(void *handle) { alarm__str *p; alarm__str *q; p=(alarm__str *)&alarm__all; while (p->next) { if (p->next->handle==handle) { q=p->next; p->next=q->next; mem_free(q); } else p=p->next; } } /* * BOOL alarm_anypending(void *handle) * * Use * Returns TRUE if there are alarms for the given handle */ BOOL alarm_anypending(void *handle) { alarm__str *p=alarm__all; while (p) { if (p->handle==handle) return (TRUE); p=p->next; } return (FALSE); } /* * BOOL alarm_next(int *when) * * Use * Informs the caller (a) if there are any alarms waiting, and (b) when * the next one is. * * Parameters * int *when == where to put the next time for an alarm (unchanged if no * alarm is set) * * Returns * TRUE if there are any alarms left */ BOOL alarm_next(int *when) { if (alarm__all) { *when=alarm__all->time; return (TRUE); } else return (FALSE); } /* * void alarm_callnext(void) * * Use * Calls the next alarm and removes it from the list */ void alarm_callnext(void) { alarm__str a; if (!alarm__all) return; a=*alarm__all; mem_free(alarm__all); alarm__all=a.next; a.proc(a.time,a.handle); }