chiark / gitweb /
Initial revision
[ssr] / StraySrc / Libraries / Steel / c / alarm
1 /*
2  * alarm.c
3  *
4  * Calling routines at set times
5  *
6  * © 1994-1998 Straylight
7  */
8
9 /*----- Licensing note ----------------------------------------------------*
10  *
11  * This file is part of Straylight's Steel library.
12  *
13  * Steel is free software; you can redistribute it and/or modify
14  * it under the terms of the GNU General Public License as published by
15  * the Free Software Foundation; either version 2, or (at your option)
16  * any later version.
17  *
18  * Steel is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with Steel.  If not, write to the Free Software Foundation,
25  * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26  */
27
28 #include "alarm.h"
29 #include "mem.h"
30 #include "werr.h"
31 #include "msgs.h"
32 #include "os.h"
33 #include "swiv.h"
34 #include "swis.h"
35
36 typedef struct alarm__str
37 {
38   struct alarm__str *next;
39   alarm_handler proc;
40   void *handle;
41   int time;
42 }
43 alarm__str;
44
45 static alarm__str *alarm__all;
46
47 /*
48  * void alarm_init(void)
49  *
50  * Use
51  *  None at all
52  */
53
54 void alarm_init(void)
55 {
56   /* Hmmm.... this *is* an interesting function */
57 }
58
59 /*
60  * int alarm_timenow(void)
61  *
62  * Use
63  *  Reports the time right now
64  */
65
66 int alarm_timenow(void)
67 {
68   return (_swi(OS_ReadMonotonicTime,_return(0)));
69 }
70
71 /*
72  * int alarm_timedifference(int t1,int t2)
73  *
74  * Use
75  *  Tells you the difference between two times.  t2 is considered to be later
76  *  than t1.
77  */
78
79 int alarm_timedifference(int t1,int t2)
80 {
81   /* --- Humm.... How to deal with wraparound --- *
82    *
83    * Answer: Ignore it and subtract -- mod 2^32 arithmetic + 2s complement
84    * sorts it all out for you.
85    */
86
87   return (t2-t1);
88 }
89
90 /*
91  * void alarm_set(int at,alarm_handler proc,void *handle)
92  *
93  * Use
94  *  Sets up `proc' to be called at time `at', being passed `handle'.
95  */
96
97 void alarm_set(int at,alarm_handler proc,void *handle)
98 {
99   alarm__str *a=mem_alloc(sizeof(alarm__str));
100   alarm__str *p;
101   if (!a)
102     werr(FALSE,msgs_lookup("alarmNEM:Not enough memory for alarm"));
103   else
104   {
105     /* --- Fill in the structure --- */
106
107     a->time=at;
108     a->proc=proc;
109     a->handle=handle;
110
111     /* --- Scan the list and put the new node in the right place --- *
112      *
113      * Is this the right condition for the times?
114      */
115
116     p=(alarm__str *)&alarm__all;
117     while (p->next && p->next->time<at)
118       p=p->next;
119     a->next=p->next;
120     p->next=a;
121   }
122 }
123
124 /*
125  * void alarm_remove(int at,void *handle)
126  *
127  * Use
128  *  Removes an alarm identified by a time and a handle
129  */
130
131 void alarm_remove(int at,void *handle)
132 {
133   alarm__str *p;
134   alarm__str *q;
135
136   p=(alarm__str *)&alarm__all;
137   while (p->next)
138   {
139     if (p->next->time==at && p->next->handle==handle)
140     {
141       q=p->next;
142       p->next=q->next;
143       mem_free(q);
144       return;
145     }
146     p=p->next;
147   }
148 }
149
150 /*
151  * void alarm_removeall(void *handle)
152  *
153  * Use
154  *  Removes all alarms for the given handle
155  */
156
157 void alarm_removeall(void *handle)
158 {
159   alarm__str *p;
160   alarm__str *q;
161
162   p=(alarm__str *)&alarm__all;
163   while (p->next)
164   {
165     if (p->next->handle==handle)
166     {
167       q=p->next;
168       p->next=q->next;
169       mem_free(q);
170     }
171     else
172       p=p->next;
173   }
174 }
175
176 /*
177  * BOOL alarm_anypending(void *handle)
178  *
179  * Use
180  *  Returns TRUE if there are alarms for the given handle
181  */
182
183 BOOL alarm_anypending(void *handle)
184 {
185   alarm__str *p=alarm__all;
186
187   while (p)
188   {
189     if (p->handle==handle)
190       return (TRUE);
191     p=p->next;
192   }
193   return (FALSE);
194 }
195
196 /*
197  * BOOL alarm_next(int *when)
198  *
199  * Use
200  *  Informs the caller (a) if there are any alarms waiting, and (b) when
201  *  the next one is.
202  *
203  * Parameters
204  *  int *when == where to put the next time for an alarm (unchanged if no
205  *    alarm is set)
206  *
207  * Returns
208  *  TRUE if there are any alarms left
209  */
210
211 BOOL alarm_next(int *when)
212 {
213   if (alarm__all)
214   {
215     *when=alarm__all->time;
216     return (TRUE);
217   }
218   else
219     return (FALSE);
220 }
221
222 /*
223  * void alarm_callnext(void)
224  *
225  * Use
226  *  Calls the next alarm and removes it from the list
227  */
228
229 void alarm_callnext(void)
230 {
231   alarm__str a;
232
233   if (!alarm__all)
234     return;
235
236   a=*alarm__all;
237   mem_free(alarm__all);
238   alarm__all=a.next;
239   a.proc(a.time,a.handle);
240 }