X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~mdw/git/mLib/blobdiff_plain/b78d1e6d0c48905d2b32a5019f7d5aef3119ae51..1101f87ace7e0b3be886220d4faa13954fd35c6b:/sel.c diff --git a/sel.c b/sel.c index de8cdef..a9dd4cf 100644 --- a/sel.c +++ b/sel.c @@ -1,6 +1,6 @@ /* -*-c-*- * - * $Id: sel.c,v 1.4 1999/08/19 18:30:26 mdw Exp $ + * $Id: sel.c,v 1.5 1999/08/31 17:42:22 mdw Exp $ * * I/O multiplexing support * @@ -30,6 +30,9 @@ /*----- Revision history --------------------------------------------------* * * $Log: sel.c,v $ + * Revision 1.5 1999/08/31 17:42:22 mdw + * New function `sel_force' to force a descriptor to be `selected'. + * * Revision 1.4 1999/08/19 18:30:26 mdw * Implement hooks for foreign select-using systems (currently not well * tested). @@ -71,12 +74,15 @@ void sel_init(sel_state *s) { - s->files = 0; + int i; + + for (i = 0; i < SEL_MODES; i++) { + s->files[i] = 0; + FD_ZERO(&s->fd[i]); + } s->timers = 0; s->hooks = 0; - FD_ZERO(&s->fd[SEL_READ]); - FD_ZERO(&s->fd[SEL_WRITE]); - FD_ZERO(&s->fd[SEL_EXC]); + s->args = 0; } /* --- @sel_initfile@ --- * @@ -118,7 +124,7 @@ void sel_initfile(sel_state *s, sel_file *f, void sel_addfile(sel_file *f) { - sel_file **ff = &f->s->files; + sel_file **ff = &f->s->files[f->mode]; /* --- This little dance looks like line-noise, but it does the job --- */ @@ -132,6 +138,24 @@ void sel_addfile(sel_file *f) FD_SET(f->fd, f->s->fd + f->mode); } +/* --- @sel_force@ --- * + * + * Arguments: @sel_file *f@ = pointer to file selector + * + * Returns: --- + * + * Use: Forces a file selector to be considered ready. This is only + * useful during a call to @sel_select@. Of particular use is + * forcing a write selector when there's something interesting + * ready for it. + */ + +void sel_force(sel_file *f) +{ + if (f->s->args) + FD_SET(f->fd, &f->s->args->fd[f->mode]); +} + /* --- @sel_rmfile@ --- * * * Arguments: @sel_file *f@ = pointer to a file block @@ -286,7 +310,15 @@ int sel_select(sel_state *s) /* --- Initialize the argument block --- */ - a.maxfd = s->files ? s->files->fd + 1 : 0; + { + int i; + a.maxfd = 0; + for (i = 0; i < SEL_MODES; i++) { + if (s->files[i] && s->files[i]->fd >= a.maxfd) + a.maxfd = s->files[i]->fd + 1; + } + } + memcpy(a.fd, s->fd, sizeof(a.fd)); if (s->timers || s->hooks) gettimeofday(&a.now, 0); @@ -296,6 +328,7 @@ int sel_select(sel_state *s) TV_SUB(&a.tv, &s->timers->tv, &a.now); a.tvp = &a.tv; } + s->args = &a; /* --- Grind through the pre hooks --- */ @@ -313,8 +346,10 @@ int sel_select(sel_state *s) if ((err = select(a.maxfd, &a.fd[SEL_READ], &a.fd[SEL_WRITE], &a.fd[SEL_EXC], - a.tvp)) < 0) + a.tvp)) < 0) { + s->args = 0; return (err); + } if (a.tvp) gettimeofday(&a.now, 0); @@ -345,17 +380,27 @@ int sel_select(sel_state *s) t->prev = (sel_timer *)&s->timers; } - /* --- And finally run through the files --- */ + /* --- And finally run through the files --- * + * + * Do reads first. It's quite possible that a read might prompt a write, + * but the other way around is less likely. Fortunately, the modes are + * in the right order for this. + */ { - sel_file *f, *ff; - for (f = s->files; f; f = ff) { - ff = f->next; - if (FD_ISSET(f->fd, a.fd + f->mode)) - f->func(f->fd, f->mode, f->p); + int i; + + for (i = 0; i < SEL_MODES; i++) { + sel_file *f, *ff; + for (f = s->files[i]; f; f = ff) { + ff = f->next; + if (FD_ISSET(f->fd, a.fd + f->mode)) + f->func(f->fd, f->mode, f->p); + } } } + s->args = 0; return (0); }