diff options
-rw-r--r-- | ChangeLog | 9 | ||||
-rw-r--r-- | jim-eventloop.c | 130 | ||||
-rw-r--r-- | jim-eventloop.h | 14 |
3 files changed, 118 insertions, 35 deletions
@@ -1,3 +1,12 @@ +2008-07-07 Uwe Klein <uklein@klein-messgeraete.de> + + * changes to jim-eventloop.[ch] + * fix negative displacement in timeout computation for select + * add basic support for the fileevent stuff [ used from jim-aio ] + * add basic support for signal handling / actions + * add basic support for timer [via after] restart, cancel + and returning the remaining time for cancled events + 2008-07-07 oharboe * src/jim.c: remove bogus return value from if {[expr]} {xx} when diff --git a/jim-eventloop.c b/jim-eventloop.c index 7fbf571..4a7acba 100644 --- a/jim-eventloop.c +++ b/jim-eventloop.c @@ -33,6 +33,9 @@ #include <sys/time.h> #include <sys/types.h> #include <unistd.h> +#include <sys/select.h> +#include <errno.h> + extern int errno; /* --- */ /* File event structure */ @@ -48,6 +51,8 @@ typedef struct Jim_FileEvent { /* Time event structure */ typedef struct Jim_TimeEvent { jim_wide id; /* time event identifier. */ + int mode; /* restart, repetitive .. UK */ + long initialms; /* initial relativ timer value UK */ long when_sec; /* seconds */ long when_ms; /* milliseconds */ Jim_TimeProc *timeProc; @@ -70,6 +75,7 @@ void Jim_CreateFileHandler(Jim_Interp *interp, void *handle, int mask, Jim_FileEvent *fe; Jim_EventLoop *eventLoop = Jim_GetAssocData(interp, "eventloop"); + // fprintf(stderr,"rein\n"); fe = Jim_Alloc(sizeof(*fe)); fe->handle = handle; fe->mask = mask; @@ -78,6 +84,7 @@ void Jim_CreateFileHandler(Jim_Interp *interp, void *handle, int mask, fe->clientData = clientData; fe->next = eventLoop->fileEventHead; eventLoop->fileEventHead = fe; + // fprintf(stderr,"raus\n"); } void Jim_DeleteFileHandler(Jim_Interp *interp, void *handle) @@ -102,6 +109,16 @@ void Jim_DeleteFileHandler(Jim_Interp *interp, void *handle) } } +// The same for signals. +void Jim_CreateSignalHandler(Jim_Interp *interp, int signum, + Jim_FileProc *proc, void *clientData, + Jim_EventFinalizerProc *finalizerProc) +{ +} +void Jim_DeleteSignalHandler(Jim_Interp *interp, int signum) +{ +} + /* That's another part of this extension that needs to be ported * to WIN32. */ static void JimGetTime(long *seconds, long *milliseconds) @@ -126,6 +143,8 @@ jim_wide Jim_CreateTimeHandler(Jim_Interp *interp, jim_wide milliseconds, te = Jim_Alloc(sizeof(*te)); te->id = id; + te->mode = 0; + te->initialms = milliseconds; te->when_sec = cur_sec + milliseconds/1000; te->when_ms = cur_ms + milliseconds%1000; if (te->when_ms >= 1000) { @@ -140,14 +159,24 @@ jim_wide Jim_CreateTimeHandler(Jim_Interp *interp, jim_wide milliseconds, return id; } -int Jim_DeleteTimeHandler(Jim_Interp *interp, jim_wide id) +jim_wide Jim_DeleteTimeHandler(Jim_Interp *interp, jim_wide id) { Jim_TimeEvent *te, *prev = NULL; Jim_EventLoop *eventLoop = Jim_GetAssocData(interp, "eventloop"); + long cur_sec, cur_ms; + jim_wide remain ; + + JimGetTime(&cur_sec, &cur_ms); te = eventLoop->timeEventHead; + if (id >= eventLoop->timeEventNextId) + return -2; /* wrong event ID */ while(te) { if (te->id == id) { + remain = (te->when_sec - cur_sec) * 1000; + remain += (te->when_ms - cur_ms) ; + remain = (remain < 0) ? 0 : remain ; + if (prev == NULL) eventLoop->timeEventHead = te->next; else @@ -155,12 +184,12 @@ int Jim_DeleteTimeHandler(Jim_Interp *interp, jim_wide id) if (te->finalizerProc) te->finalizerProc(interp, te->clientData); Jim_Free(te); - return JIM_OK; + return remain; } prev = te; te = te->next; } - return JIM_ERR; /* NO event with the specified ID found */ + return -1; /* NO event with the specified ID found */ } /* Search the first timer to fire. @@ -217,9 +246,10 @@ int Jim_ProcessEvents(Jim_Interp *interp, int flags) /* Check file events */ while (fe != NULL) { - int fd = (int) fe->handle; + int fd = fileno(fe->handle); - if (fe->mask & JIM_EVENT_READABLE) FD_SET(fd, &rfds); + if (fe->mask & JIM_EVENT_READABLE) + FD_SET(fd, &rfds); if (fe->mask & JIM_EVENT_WRITABLE) FD_SET(fd, &wfds); if (fe->mask & JIM_EVENT_EXCEPTION) FD_SET(fd, &efds); if (maxfd < fd) maxfd = fd; @@ -234,6 +264,7 @@ int Jim_ProcessEvents(Jim_Interp *interp, int flags) int retval; Jim_TimeEvent *shortest; struct timeval tv, *tvp; + jim_wide dt; shortest = JimSearchNearestTimer(eventLoop); if (shortest) { @@ -243,22 +274,32 @@ int Jim_ProcessEvents(Jim_Interp *interp, int flags) * timer to fire. */ JimGetTime(&now_sec, &now_ms); tvp = &tv; - tvp->tv_sec = shortest->when_sec - now_sec; - if (shortest->when_ms < now_ms) { - tvp->tv_usec = ((shortest->when_ms+1000) - now_ms)*1000; - tvp->tv_sec --; - } else { - tvp->tv_usec = (shortest->when_ms - now_ms)*1000; - } + dt = 1000 * (shortest->when_sec - now_sec); + dt += ( shortest->when_ms - now_ms); + if (dt < 0) { + dt = 1; + } + tvp->tv_sec = dt / 1000; + tvp->tv_usec = dt % 1000; + // fprintf(stderr,"Next %d.% 8d\n",(int)tvp->tv_sec,(int)tvp->tv_usec); } else { tvp = NULL; /* wait forever */ + // fprintf(stderr,"No Event\n"); } retval = select(maxfd+1, &rfds, &wfds, &efds, tvp); - if (retval) { + if (retval < 0) { + switch (errno) { + case EINTR: fprintf(stderr,"select EINTR\n"); break; + case EINVAL: fprintf(stderr,"select EINVAL\n"); break; + case ENOMEM: fprintf(stderr,"select ENOMEM\n"); break; + } + } else if (retval > 0) { fe = eventLoop->fileEventHead; while(fe != NULL) { - int fd = (int) fe->handle; + int fd = fileno(fe->handle); + + // fprintf(stderr,"fd: %d mask: %02x \n",fd,fe->mask); if ((fe->mask & JIM_EVENT_READABLE && FD_ISSET(fd, &rfds)) || (fe->mask & JIM_EVENT_WRITABLE && FD_ISSET(fd, &wfds)) || @@ -266,8 +307,11 @@ int Jim_ProcessEvents(Jim_Interp *interp, int flags) { int mask = 0; - if (fe->mask & JIM_EVENT_READABLE && FD_ISSET(fd, &rfds)) + if (fe->mask & JIM_EVENT_READABLE && FD_ISSET(fd, &rfds)) { mask |= JIM_EVENT_READABLE; + if ((fe->mask & JIM_EVENT_FEOF) && feof(fe->handle)) + mask |= JIM_EVENT_FEOF; + } if (fe->mask & JIM_EVENT_WRITABLE && FD_ISSET(fd, &wfds)) mask |= JIM_EVENT_WRITABLE; if (fe->mask & JIM_EVENT_EXCEPTION && FD_ISSET(fd, &efds)) @@ -399,23 +443,51 @@ static int JimELAfterCommand(Jim_Interp *interp, int argc, { jim_wide ms, id; Jim_Obj *objPtr, *idObjPtr; - - if (argc != 3) { - Jim_WrongNumArgs(interp, 1, argv, "after milliseconds script"); + const char *options[] = { + "info", "cancel", "restart", "expire", NULL + }; + enum {INFO, CANCEL, RESTART, EXPIRE, CREATE }; + int option = CREATE ; + + if (argc < 3) { + Jim_WrongNumArgs(interp, 1, argv, "<after milliseconds> script"); return JIM_ERR; } if (Jim_GetWide(interp, argv[1], &ms) != JIM_OK) + if (Jim_GetEnum(interp, argv[1], options, &option, "after options", + JIM_ERRMSG) != JIM_OK) + return JIM_ERR; + switch (option) { + case CREATE: + Jim_IncrRefCount(argv[2]); + id = Jim_CreateTimeHandler(interp, ms, JimAfterTimeHandler, argv[2], + JimAfterTimeEventFinalizer); + objPtr = Jim_NewStringObj(interp, NULL, 0); + Jim_AppendString(interp, objPtr, "after#", -1); + idObjPtr = Jim_NewIntObj(interp, id); + Jim_IncrRefCount(idObjPtr); + Jim_AppendObj(interp, objPtr, idObjPtr); + Jim_DecrRefCount(interp, idObjPtr); + Jim_SetResult(interp, objPtr); + return JIM_OK; + case CANCEL: + { + int tlen ; + jim_wide remain = 0; + const char *tok = Jim_GetString(argv[2], &tlen); + if ( sscanf(tok,"after#%lld",&id) == 1) { + remain = Jim_DeleteTimeHandler(interp, id); + if (remain > -2) { + Jim_SetResult(interp, Jim_NewIntObj(interp, remain)); + return JIM_OK; + } + } + Jim_SetResultString(interp, "invalid event" , -1); return JIM_ERR; - Jim_IncrRefCount(argv[2]); - id = Jim_CreateTimeHandler(interp, ms, JimAfterTimeHandler, argv[2], - JimAfterTimeEventFinalizer); - objPtr = Jim_NewStringObj(interp, NULL, 0); - Jim_AppendString(interp, objPtr, "after#", -1); - idObjPtr = Jim_NewIntObj(interp, id); - Jim_IncrRefCount(idObjPtr); - Jim_AppendObj(interp, objPtr, idObjPtr); - Jim_DecrRefCount(interp, idObjPtr); - Jim_SetResult(interp, objPtr); + } + default: + fprintf(stderr,"unserviced option to after %d\n",option); + } return JIM_OK; } @@ -430,7 +502,7 @@ int Jim_OnLoad(Jim_Interp *interp) eventLoop = Jim_Alloc(sizeof(*eventLoop)); eventLoop->fileEventHead = NULL; eventLoop->timeEventHead = NULL; - eventLoop->timeEventNextId = 0; + eventLoop->timeEventNextId = 1; Jim_SetAssocData(interp, "eventloop", JimELAssocDataDeleProc, eventLoop); Jim_CreateCommand(interp, "vwait", JimELVwaitCommand, NULL, NULL); diff --git a/jim-eventloop.h b/jim-eventloop.h index 80cf113..caf89d7 100644 --- a/jim-eventloop.h +++ b/jim-eventloop.h @@ -31,6 +31,7 @@ #define __JIM_EVENTLOOP_H__ typedef int Jim_FileProc(Jim_Interp *interp, void *clientData, int mask); +typedef int Jim_SignalProc(Jim_Interp *interp, void *clientData, void *msg); typedef void Jim_TimeProc(Jim_Interp *interp, void *clientData); typedef void Jim_EventFinalizerProc(Jim_Interp *interp, void *clientData); @@ -38,6 +39,7 @@ typedef void Jim_EventFinalizerProc(Jim_Interp *interp, void *clientData); #define JIM_EVENT_READABLE 1 #define JIM_EVENT_WRITABLE 2 #define JIM_EVENT_EXCEPTION 4 +#define JIM_EVENT_FEOF 8 #ifndef __JIM_EVENTLOOP_CORE__ # if defined JIM_EXTENSION || defined JIM_EMBEDDED @@ -62,7 +64,7 @@ JIM_STATIC jim_wide JIM_API(Jim_CreateTimeHandler) (Jim_Interp *interp, jim_wide milliseconds, Jim_TimeProc *proc, void *clientData, Jim_EventFinalizerProc *finalizerProc); -JIM_STATIC int JIM_API(Jim_DeleteTimeHandler) (Jim_Interp *interp, jim_wide id); +JIM_STATIC jim_wide JIM_API(Jim_DeleteTimeHandler) (Jim_Interp *interp, jim_wide id); JIM_STATIC int JIM_API(Jim_ProcessEvents) (Jim_Interp *interp, int flags); #undef JIM_STATIC @@ -77,11 +79,11 @@ JIM_STATIC int JIM_API(Jim_ProcessEvents) (Jim_Interp *interp, int flags); /* This must be included "inline" inside the extension */ static void Jim_ImportEventloopAPI(Jim_Interp *interp) { - JIM_GET_API(Jim_CreateFileHandler); - JIM_GET_API(Jim_DeleteFileHandler); - JIM_GET_API(Jim_CreateTimeHandler); - JIM_GET_API(Jim_DeleteTimeHandler); - JIM_GET_API(Jim_ProcessEvents); + JIM_GET_API(CreateFileHandler); + JIM_GET_API(DeleteFileHandler); + JIM_GET_API(CreateTimeHandler); + JIM_GET_API(DeleteTimeHandler); + JIM_GET_API(ProcessEvents); } #endif /* defined JIM_EXTENSION || defined JIM_EMBEDDED */ #undef JIM_GET_API |