/* * Copyright (c) 1996 Gunther Schadow. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #pragma implementation #include "FdSet.h" #include #include #include /* It is likely that other systems than BSD declare fd_set slightly differently causing some headache when this is ported. For your reference here are the BSD declarations from : > #ifndef _POSIX_SOURCE > #define NBBY 8 // number of bits in a byte > > > // Select uses bit masks of file descriptors in longs. These macros > // manipulate such bit fields (the filesystem macros use chars). > // FD_SETSIZE may be defined by the user, but the default here should > // be enough for most uses. > > #ifndef FD_SETSIZE > #define FD_SETSIZE 256 > #endif > > typedef long fd_mask; > #define NFDBITS (sizeof(fd_mask) * NBBY) // bits per mask > > #ifndef howmany > #define howmany(x, y) (((x)+((y)-1))/(y)) > #endif > > typedef struct fd_set { > fd_mask fds_bits[howmany(FD_SETSIZE, NFDBITS)]; > } fd_set; > > #define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS))) > #define FD_CLR(n, p) ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS))) > #define FD_ISSET(n, p) ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS))) > #define FD_ZERO(p) bzero((char *)(p), sizeof(*(p))) */ // loosen the dependency (a good place for `#ifdef's!) const int bps = FD_SETSIZE; // bits per set const int bpm = NFDBITS; // bits per mask const int mps = howmany(bps, bpm); // masks per set int FdSet::next(int n) const { n++; int im = n / bpm; int ib = n % bpm; do { fd_mask m = fds_bits[im]; if(m != 0) for(fd_mask tm = 1 << ib; ib < bpm; ib++, tm <<= 1) if(m & tm) return im * bpm + ib; im++; ib = 0; } while(im < mps); return -1; } int FdSet::prev(int n) const { if(n == -1) n = bps; n--; int im = n / bpm; int ib = n % bpm; do { fd_mask m = fds_bits[im]; if(m != 0) for(fd_mask tm = 1 << ib; ib >= 0; ib--, tm >>= 1) if(m & tm) return im * bpm + ib; im--; ib = bpm - 1; } while(im >= 0); return -1; } #include FdSet::FdSet(int fd ...) { va_list ap; FD_ZERO(this); for(va_start(ap, fd); fd > -1; fd = va_arg(ap, int)) FD_SET(fd, this); va_end(ap); } int FdSet::select(FdSet *r, FdSet *w, FdSet *e, u_int sec, u_int usec) const { struct timeval tv = {sec, usec}; if(r != NULL) *r = *this; if(w != NULL) *w = *this; if(e != NULL) *e = *this; return ::select(nfds(), r, w, e, &tv); } int FdSet::select(FdSet *r, FdSet *w, FdSet *e) const { if(r != NULL) *r = *this; if(w != NULL) *w = *this; if(e != NULL) *e = *this; return ::select(nfds(), r, w, e, NULL); } /* * Test your port with this function: */ #ifdef FD_SET_TESTME #include main() { FdSet fds; fds.set(4); fds.set(19); fds.set(23); fds.set(36); fds.set(100); fds.set(200); fds.set(250); int fd; for(fd = fds.first(); fd >= 0; fd = fds.next(fd)) cout << fd << ", " << flush; cout << endl; for(fd = fds.last(); fd >= 0; fd = fds.prev(fd)) cout << fd << ", " << flush; cout << endl; fds.zero(); fds.set(0); fds.set(1); fds.set(2); FdSet r, w, e; int n = fds.select(&r, &w, &e); cout << "select returned " << n << endl; cout << endl << "read: "; for( fd = r.first(); fd >= 0; fd = r.next(fd)) cout << fd << ", " << flush; cout << endl << "write: "; for( fd = w.first(); fd >= 0; fd = w.next(fd)) cout << fd << ", " << flush; cout << endl << "exception: "; for( fd = e.first(); fd >= 0; fd = e.next(fd)) cout << fd << ", " << flush; cout << endl; } #endif