3
/* Poll a set of streams to see if any is available for I/O.
4
** Ready streams are moved to front of array but retain the
5
** same relative order.
7
** Written by Kiem-Phong Vo.
11
int sfpoll(Sfio_t** fa, reg int n, int tm)
14
Sfio_t** fa; /* array of streams to poll */
15
reg int n; /* number of streams in array */
16
int tm; /* the amount of time in ms to wait for selecting */
22
reg int *status, *check;
27
if(!(status = (int*)malloc(2*n*sizeof(int))) )
29
else check = status+n;
31
/* this loop partitions the streams into 3 sets: Check, Ready, Notready */
32
retry: for(r = c = 0; r < n; ++r)
35
/* this loop pops a stream stack as necessary */
37
{ /* check accessibility */
39
if((int)f->mode != m && _sfmode(f,m,0) < 0)
46
/* has discipline, ask its opinion */
47
for(d = f->disc; d; d = d->disc)
51
{ if((m = (*d->exceptf)(f,SF_DPOLL,&tm,d)) < 0)
55
/*else check file descriptor*/
58
/* unseekable stream, must check for blockability */
62
/* string/regular streams with no possibility of blocking */
66
/* stacked regular file stream with I/O possibility */
67
if(!(f->flags&SF_STRING) &&
68
((f->mode&SF_WRITE) || f->here < f->extent) )
71
/* at an apparent eof, pop stack if ok, then recheck */
73
switch(_sfexcept(f,f->mode&SF_RDWR,0,f->disc))
76
if(f->flags&SF_STRING)
80
if(f->flags&SF_STRING)
88
do_check: /* local function to set a stream for further checking */
95
do_ready: /* local function to set the ready streams */
100
do_never: /* local function to set the not-ready streams */
108
{ struct pollfd* fds;
110
/* construct the poll array */
111
if(!(fds = (struct pollfd*)malloc(c*sizeof(struct pollfd))) )
113
for(r = 0; r < c; r++)
114
{ fds[r].fd = fa[check[r]]->file;
115
fds[r].events = (fa[check[r]]->mode&SF_READ) ? POLLIN : POLLOUT;
119
for(;;) /* this loop takes care of interrupts */
120
{ if((r = SFPOLL(fds,c,tm)) == 0)
123
{ if(errno == EINTR || errno == EAGAIN)
130
for(r = 0; r < c; ++r)
132
if(((f->mode&SF_READ) && (fds[r].revents&POLLIN)) ||
133
((f->mode&SF_WRITE) && (fds[r].revents&POLLOUT)) )
134
status[check[r]] = 1;
146
struct timeval tmb, *tmp;
151
for(r = 0; r < c; ++r)
157
else FD_SET(f->file,&wr);
160
tmp = NIL(struct timeval*);
163
tmb.tv_sec = tm/SECOND;
164
tmb.tv_usec = (tm%SECOND)*SECOND;
167
{ if((r = select(m+1,&rd,&wr,NIL(fd_set*),tmp)) == 0)
175
for(r = 0; r < c; ++r)
177
if(((f->mode&SF_READ) && FD_ISSET(f->file,&rd)) ||
178
((f->mode&SF_WRITE) && FD_ISSET(f->file,&wr)) )
179
status[check[r]] = 1;
184
#endif /*_lib_select*/
186
/* call exception functions */
187
for(c = 0; c < n; ++c)
190
if((d = fa[c]->disc) && d->exceptf)
191
{ if((r = (*d->exceptf)(fa[c],SF_READY,(Void_t*)0,d)) < 0)
198
/* move ready streams to the front */
199
for(r = c = 0; c < n; ++c)
211
free((Void_t*)status);