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
44#if defined(_WIN32) || defined(__CYGWIN__)
45#include <sys/select.h>
79static TF timefunc_null = {0, 0, NULL, NULL, 0, NULL};
80static TF *timefunc = &timefunc_null;
82#define EPOCHDT(tp) (((tp)->tv_usec) / 1000.0 + ((tp)->tv_sec) * 1000.0)
99static void runWorkProc(
void);
100static void callCallback(fd_set *rfdp);
101static void checkTimer();
102static void oneLoop(
void);
103static void deferTO(
void *p);
104static void runImmediates();
125 int totid = maxms ?
addTimer(maxms, deferTO, &toflag) : 0;
148 int totid = maxms ?
addTimer(maxms, deferTO, &toflag) : 0;
170 for (cp = cback; cp < &cback[ncback]; cp++)
173 if (cp == &cback[ncback])
175 cback = realloc(cback, (ncback + 1) *
sizeof(
CB));
176 cp = &cback[ncback++];
198 if (cid < 0 || cid >= ncback)
210static void insertTimer(
TF *node)
214 for(; ; it = it->
next)
235 gettimeofday(&t, NULL);
238 node = (
TF*)malloc(
sizeof(
TF));
244 node->tgo =
EPOCHDT(&t) + delay;
245 node->interval = interval;
254 return addTimerImpl(ms, 0, fp, ud);
259 return addTimerImpl(ms, ms, fp, ud);
263static TF *dettachTimer(
TF *node)
266 for(; it->
next != NULL; it = it->
next)
268 if (it->
next == node)
278static TF *findTimer(
int timer_id)
281 for(; it != NULL; it = it->
next)
282 if (it->
tid == timer_id)
292 TF *node, *it = timefunc;
293 for(; (node = it->
next) != NULL; it = it->
next)
295 if (node->
tid == timer_id)
305static double remainingTimerNode(
TF *node)
308 gettimeofday(&now, NULL);
317 TF *it = findTimer(timer_id);
318 return it == NULL ? -1 : remainingTimerNode(it);
326 TF *it = findTimer(timer_id);
327 return it == NULL ? -1 : remainingTimerNode(it) * 1000000;
338 for (wp = wproc; wp < &wproc[nwproc]; wp++)
341 if (wp == &wproc[nwproc])
343 wproc = (
WP *)realloc(wproc, (nwproc + 1) *
sizeof(
WP));
344 wp = &wproc[nwproc++];
365 if (wid < 0 || wid >= nwproc)
377static void runWorkProc()
388 lastwp = (lastwp + 1) % nwproc;
397static void callCallback(fd_set *rfdp)
408 lastcb = (lastcb + 1) % ncback;
410 }
while (!cp->
in_use || !FD_ISSET(cp->
fd, rfdp));
413 (*cp->
fp)(cp->
fd, cp->
ud);
420static void checkTimer()
422 TF *node = timefunc->
next;
424 if (node == NULL || remainingTimerNode(node) > 0)
427 (*node->
fp)(node->
ud);
429 node = dettachTimer(node);
448 struct timeval tv, *tvp;
456 for (cp = cback; cp < &cback[ncback]; cp++)
460 FD_SET(cp->
fd, &rfd);
477 tvp->tv_sec = tvp->tv_usec = 0;
479 else if (timefunc->
next != NULL)
481 double late = remainingTimerNode(timefunc->
next);
486 tvp->tv_sec = (long)floor(late);
487 tvp->tv_usec = (long)floor((late - tvp->tv_sec) * 1000000.0);
493 ns = select(maxfd + 1, &rfd, NULL, NULL, tvp);
513static void deferTO(
void *p)
533 immediate->
prev = lastImmediate;
534 immediate->
next = NULL;
536 lastImmediate->
next = immediate;
538 firstImmediate = immediate;
540 lastImmediate = immediate;
543static int peekImmediate(
Immediate * into)
545 if (!firstImmediate) {
552 firstImmediate = o->
next;
556 lastImmediate = NULL;
563void runImmediates() {
565 while((peekImmediate(&immediate))) {
566 (*immediate.
fp)(immediate.
ud);
572typedef void(
IE_CBF)(
int readfiledes,
void *userpointer);
631#if defined(MAIN_TEST)
650 gettimeofday(&tv, NULL);
651 printf(
"workproc @ %ld.%03ld %d %d\n", (
long)tv.tv_sec, (
long)tv.tv_usec / 1000, counter, ++(*(
int *)ud));
656 printf(
"timeout %d\n", (
int)ud);
659void stdinCB(
int fd,
void *ud)
663 if (read(
fd, &c, 1) != 1)
693 mytid =
addTimer(1000, to, (
void *)1);
696 mytid =
addTimer(2000, to, (
void *)2);
699 mytid =
addTimer(3000, to, (
void *)3);
702 mytid =
addTimer(4000, to, (
void *)4);
705 mytid =
addTimer(5000, to, (
void *)5);
711 printf(
"callback: %d\n", ++(*(
int *)ud));
714int 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.
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.