+++ /dev/null
-/* $Id$ $Revision$ */
-/* vim:set shiftwidth=4 ts=8: */
-
-/*************************************************************************
- * Copyright (c) 2011 AT&T Intellectual Property
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors: See CVS logs. Details at http://www.graphviz.org/
- *************************************************************************/
-
-#include <sfio/sfhdr.h>
-
-/* Poll a set of streams to see if any is available for I/O.
-** Ready streams are moved to front of array but retain the
-** same relative order.
-**
-** Written by Kiem-Phong Vo.
-*/
-
-/**
- * @param fa array of streams to poll
- * @param n number of streams in array
- * @param tm the amount of time in ms to wait for selecting
- */
-int sfpoll(Sfio_t ** fa, int n, int tm)
-{
- int r, c, m;
- Sfio_t *f;
- Sfdisc_t *d;
- int *status, *check;
-
- if (n <= 0 || !fa)
- return -1;
-
- if (!(status = (int *) malloc(2 * n * sizeof(int))))
- return -1;
- else
- check = status + n;
-
- /* this loop partitions the streams into 3 sets: Check, Ready, Notready */
- retry:for (r = c = 0; r < n; ++r) {
- f = fa[r];
-
- /* this loop pops a stream stack as necessary */
- for (;;) { /* check accessibility */
- m = f->mode & SF_RDWR;
- if ((int) f->mode != m && _sfmode(f, m, 0) < 0)
- goto do_never;
-
- /* clearly ready */
- if (f->next < f->endb)
- goto do_ready;
-
- /* has discipline, ask its opinion */
- for (d = f->disc; d; d = d->disc)
- if (d->exceptf)
- break;
- if (d) {
- if ((m = (*d->exceptf) (f, SF_DPOLL, &tm, d)) < 0)
- goto do_never;
- else if (m > 0)
- goto do_ready;
- /*else check file descriptor */
- }
-
- /* unseekable stream, must check for blockability */
- if (f->extent < 0)
- goto do_check;
-
- /* string/regular streams with no possibility of blocking */
- if (!f->push)
- goto do_ready;
-
- /* stacked regular file stream with I/O possibility */
- if (!(f->flags & SF_STRING) &&
- ((f->mode & SF_WRITE) || f->here < f->extent))
- goto do_ready;
-
- /* at an apparent eof, pop stack if ok, then recheck */
- SETLOCAL(f);
- switch (_sfexcept(f, f->mode & SF_RDWR, 0, f->disc)) {
- case SF_EDONE:
- if (f->flags & SF_STRING)
- goto do_never;
- else
- goto do_ready;
- case SF_EDISC:
- if (f->flags & SF_STRING)
- goto do_ready;
- case SF_ESTACK:
- case SF_ECONT:
- continue;
- }
- }
-
- do_check: /* local function to set a stream for further checking */
- {
- status[r] = 0;
- check[c] = r;
- c += 1;
- continue;
- }
-
- do_ready: /* local function to set the ready streams */
- {
- status[r] = 1;
- continue;
- }
-
- do_never: /* local function to set the not-ready streams */
- {
- status[r] = -1;
- continue;
- }
- }
-
-#ifdef HAVE_SELECT
- if (c > 0) {
- fd_set rd, wr;
- struct timeval tmb, *tmp;
-
- FD_ZERO(&rd);
- FD_ZERO(&wr);
- m = 0;
- for (r = 0; r < c; ++r) {
- f = fa[check[r]];
- if (f->file > m)
- m = f->file;
- if (f->mode & SF_READ)
- FD_SET(f->file, &rd);
- else
- FD_SET(f->file, &wr);
- }
- if (tm < 0)
- tmp = NIL(struct timeval *);
- else {
- tmp = &tmb;
- tmb.tv_sec = tm / SECOND;
- tmb.tv_usec = (tm % SECOND) * SECOND;
- }
- for (;;) {
- if ((r = select(m + 1, &rd, &wr, NIL(fd_set *), tmp)) == 0)
- break;
- else if (r < 0) {
- if (errno == EINTR)
- continue;
- else
- break;
- }
-
- for (r = 0; r < c; ++r) {
- f = fa[check[r]];
- if (((f->mode & SF_READ) && FD_ISSET(f->file, &rd)) ||
- ((f->mode & SF_WRITE) && FD_ISSET(f->file, &wr)))
- status[check[r]] = 1;
- }
- break;
- }
- }
-#endif /*HAVE_SELECT*/
-
- /* call exception functions */
- for (c = 0; c < n; ++c) {
- if (status[c] <= 0)
- continue;
- if ((d = fa[c]->disc) && d->exceptf) {
- if ((r = (*d->exceptf) (fa[c], SF_READY, (void *) 0, d)) < 0)
- goto done;
- else if (r > 0)
- goto retry;
- }
- }
-
- /* move ready streams to the front */
- for (r = c = 0; c < n; ++c) {
- if (status[c] > 0) {
- if (c > r) {
- f = fa[r];
- fa[r] = fa[c];
- fa[c] = f;
- }
- r += 1;
- }
- }
-
- done:
- free((void *) status);
- return r;
-}