3 Copyright (C) 2003 Elwood C. Downey
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT
ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License
for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with
this library;
if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
41 #include <sys/types.h>
75 static TF timefunc_null = {0, 0, NULL, NULL, 0, NULL};
76 static TF *timefunc = &timefunc_null;
78 #define EPOCHDT(tp) (((tp)->tv_usec) / 1000.0 + ((tp)->tv_sec) * 1000.0)
95 static void runWorkProc(
void);
96 static void callCallback(fd_set *rfdp);
97 static void checkTimer();
98 static void oneLoop(
void);
99 static void deferTO(
void *p);
100 static void runImmediates();
121 int totid = maxms ?
addTimer(maxms, deferTO, &toflag) : 0;
144 int totid = maxms ?
addTimer(maxms, deferTO, &toflag) : 0;
166 for (cp = cback; cp < &cback[ncback]; cp++)
169 if (cp == &cback[ncback])
171 cback = realloc(cback, (ncback + 1) *
sizeof(
CB));
172 cp = &cback[ncback++];
194 if (cid < 0 || cid >= ncback)
206 static void insertTimer(
TF *node)
210 for(; ; it = it->
next)
231 gettimeofday(&t, NULL);
234 node = (
TF*)malloc(
sizeof(
TF));
240 node->tgo =
EPOCHDT(&t) + delay;
241 node->interval = interval;
250 return addTimerImpl(ms, 0, fp, ud);
255 return addTimerImpl(ms, ms, fp, ud);
259 static TF *dettachTimer(
TF *node)
262 for(; it->
next != NULL; it = it->
next)
264 if (it->
next == node)
274 static TF *findTimer(
int timer_id)
277 for(; it != NULL; it = it->
next)
278 if (it->
tid == timer_id)
288 TF *node, *it = timefunc;
289 for(; (node = it->
next) != NULL; it = it->
next)
291 if (node->
tid == timer_id)
301 static double remainingTimerNode(
TF *node)
304 gettimeofday(&now, NULL);
313 TF *it = findTimer(timer_id);
314 return it == NULL ? -1 : remainingTimerNode(it);
322 TF *it = findTimer(timer_id);
323 return it == NULL ? -1 : remainingTimerNode(it) * 1000000;
334 for (wp = wproc; wp < &wproc[nwproc]; wp++)
337 if (wp == &wproc[nwproc])
339 wproc = (
WP *)realloc(wproc, (nwproc + 1) *
sizeof(
WP));
340 wp = &wproc[nwproc++];
361 if (wid < 0 || wid >= nwproc)
373 static void runWorkProc()
384 lastwp = (lastwp + 1) % nwproc;
393 static void callCallback(fd_set *rfdp)
404 lastcb = (lastcb + 1) % ncback;
406 }
while (!cp->
in_use || !FD_ISSET(cp->
fd, rfdp));
409 (*cp->
fp)(cp->
fd, cp->
ud);
416 static void checkTimer()
418 TF *node = timefunc->
next;
420 if (node == NULL || remainingTimerNode(node) > 0)
423 (*node->
fp)(node->
ud);
425 node = dettachTimer(node);
442 static void oneLoop()
444 struct timeval tv, *tvp;
452 for (cp = cback; cp < &cback[ncback]; cp++)
456 FD_SET(cp->
fd, &rfd);
473 tvp->tv_sec = tvp->tv_usec = 0;
475 else if (timefunc->
next != NULL)
477 double late = remainingTimerNode(timefunc->
next);
482 tvp->tv_sec = (long)floor(late);
483 tvp->tv_usec = (long)floor((late - tvp->tv_sec) * 1000000.0);
489 ns = select(maxfd + 1, &rfd, NULL, NULL, tvp);
509 static void deferTO(
void *p)
521 static Immediate * firstImmediate = NULL;
529 immediate->
prev = lastImmediate;
530 immediate->
next = NULL;
532 lastImmediate->
next = immediate;
534 firstImmediate = immediate;
536 lastImmediate = immediate;
539 static int peekImmediate(
Immediate * into)
541 if (!firstImmediate) {
548 firstImmediate = o->
next;
552 lastImmediate = NULL;
559 void runImmediates() {
561 while((peekImmediate(&immediate))) {
562 (*immediate.
fp)(immediate.
ud);
568 typedef void(
IE_CBF)(
int readfiledes,
void *userpointer);
627 #if defined(MAIN_TEST)
632 #include <sys/time.h>
646 gettimeofday(&tv, NULL);
647 printf(
"workproc @ %ld.%03ld %d %d\n", (
long)tv.tv_sec, (
long)tv.tv_usec / 1000, counter, ++(*(
int *)ud));
652 printf(
"timeout %d\n", (
int)ud);
655 void stdinCB(
int fd,
void *ud)
659 if (read(
fd, &c, 1) != 1)
689 mytid =
addTimer(1000, to, (
void *)1);
692 mytid =
addTimer(2000, to, (
void *)2);
695 mytid =
addTimer(3000, to, (
void *)3);
698 mytid =
addTimer(4000, to, (
void *)4);
701 mytid =
addTimer(5000, to, (
void *)5);
707 printf(
"callback: %d\n", ++(*(
int *)ud));
710 int main(
int ac,
char *av[])
void eventLoop()
Main calls this when ready to hand over control.
int64_t IENSecsRemainingTimer(int timerid)
int IEAddPeriodicTimer(int millisecs, IE_TCF *fp, void *p)
Register a new periodic timer function, fp, to be called with ud as argument after ms.
void IERmCallback(int callbackid)
Remove a callback function.
void IERmWorkProc(int workprocid)
Remove a work procedure.
void rmTimer(int timer_id)
int addWorkProc(WPF *fp, void *ud)
void IERmTimer(int timerid)
Remove the timer with the given timerid, as returned from IEAddTimer() or IEAddPeriodicTimer().
int addTimer(int ms, TCF *fp, void *ud)
int IEAddWorkProc(IE_WPF *fp, void *p)
Add a new work procedure, fp, to be called with ud when nothing else to do.
int IEAddCallback(int readfiledes, IE_CBF *fp, void *p)
Register a new callback, fp, to be called with userpointer as argument when readfiledes is ready.
void() IE_TCF(void *userpointer)
Signature of a timeout caller.
int addPeriodicTimer(int ms, TCF *fp, void *ud)
int remainingTimer(int timer_id)
int64_t nsecsRemainingTimer(int timer_id)
void addImmediateWork(TCF *fp, void *ud)
int IEDeferLoop(int maxms, int *flagp)
wait in-line for a flag to set, presumably by another event function
int deferLoop0(int maxms, int *flagp)
int IERemainingTimer(int timerid)
Returns the timer's remaining value in milliseconds left until the timeout.
void() IE_CBF(int readfiledes, void *userpointer)
Signature of a callback.
int deferLoop(int maxms, int *flagp)
int IEAddTimer(int millisecs, IE_TCF *fp, void *p)
Register a new single-shot timer function, fp, to be called with ud as argument after ms.
struct Immediate Immediate
void() IE_WPF(void *userpointer)
Signature of a work procedure function.
int IEDeferLoop0(int maxms, int *flagp)
int addCallback(int fd, CBF *fp, void *ud)
Public interface to INDI's eventloop mechanism.
void() WPF(void *)
Signature of a work procedure function.
void() CBF(int fd, void *)
Signature of a callback function.
void() TCF(void *)
Signature of a timer function.
Namespace to encapsulate INDI client, drivers, and mediator classes.