Fl::add_fd() structures are dynamically allocated so you can listen to

as many connections as you want (up to the maximum number handled by
select()).

Fl::remove_fd(fd, when) added.  This allows you to remove the read,
write, and error callbacks individually.  Fl::remove_fd(fd) does
Fl::remove_fd(fd,-1).

Fl::add_fd() calls Fl::remove_fd(), so it can be used safely to
replace callbacks with new ones for the same file descriptor.

Fl::add_timeout() also dynamically allocates it's array so there is no
limit on the number of pending timeouts.

I cut/pasted the changes into the Windoze version but this is
UNTESTED!  Somebody please do a test compile.


git-svn-id: file:///fltk/svn/fltk/branches/branch-1.0@544 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
This commit is contained in:
Bill Spitzak 1999-04-17 01:02:30 +00:00
parent 6776041873
commit 0e29799dda
5 changed files with 172 additions and 116 deletions

View File

@ -1,5 +1,5 @@
//
// "$Id: Fl.H,v 1.8 1999/02/23 22:12:38 mike Exp $"
// "$Id: Fl.H,v 1.8.2.1 1999/04/17 01:02:27 bill Exp $"
//
// Main header file for the Fast Light Tool Kit (FLTK).
//
@ -89,8 +89,9 @@ public:
static FL_EXPORT Fl_Widget* readqueue();
static FL_EXPORT void add_timeout(double t,void (*cb)(void*),void* = 0);
static FL_EXPORT void remove_timeout(void (*cb)(void*), void* = 0);
static FL_EXPORT void add_fd(int fd, int when, void (*cb)(int, void*), void* = 0);
static FL_EXPORT void add_fd(int fd, int when, void (*cb)(int,void*),void* =0);
static FL_EXPORT void add_fd(int fd, void (*cb)(int, void*), void* = 0);
static FL_EXPORT void remove_fd(int, int when);
static FL_EXPORT void remove_fd(int);
static FL_EXPORT void add_idle(void (*cb)(void*), void* = 0);
static FL_EXPORT void remove_idle(void (*cb)(void*), void* = 0);
@ -204,5 +205,5 @@ public:
#endif
//
// End of "$Id: Fl.H,v 1.8 1999/02/23 22:12:38 mike Exp $".
// End of "$Id: Fl.H,v 1.8.2.1 1999/04/17 01:02:27 bill Exp $".
//

View File

@ -1,5 +1,5 @@
//
// "$Id: Fl.cxx,v 1.24.2.3 1999/04/10 08:09:38 bill Exp $"
// "$Id: Fl.cxx,v 1.24.2.4 1999/04/17 01:02:28 bill Exp $"
//
// Main event handling code for the Fast Light Tool Kit (FLTK).
//
@ -27,6 +27,8 @@
#include <FL/Fl_Window.H>
#include <FL/x.H>
#include <ctype.h>
#include <malloc.h>
#include <string.h>
//
// Globals...
@ -68,31 +70,36 @@ int Fl::event_inside(const Fl_Widget *o) /*const*/ {
// Timeouts are insert-sorted into order. This works good if there
// are only a small number:
#define MAXTIMEOUT 8
static struct {
static struct Timeout {
double time;
void (*cb)(void*);
void* arg;
} timeout[MAXTIMEOUT+1];
} * timeout;
static int numtimeouts;
static int timeout_array_size;
void Fl::add_timeout(double t, void (*cb)(void *), void *v) {
int i;
fl_elapsed();
if (numtimeouts<MAXTIMEOUT) numtimeouts++;
for (i=0; i<(numtimeouts-1); i++) {
if (numtimeouts >= timeout_array_size) {
timeout_array_size = 2*timeout_array_size+1;
timeout = (Timeout*)realloc(timeout, timeout_array_size*sizeof(Timeout));
}
// insert-sort the new timeout:
int i;
for (i=0; i<numtimeouts; i++) {
if (timeout[i].time > t) {
for (int j=numtimeouts-1; j>i; j--) timeout[j] = timeout[j-1];
for (int j=numtimeouts; j>i; j--) timeout[j] = timeout[j-1];
break;
}
}
timeout[i].time = t;
timeout[i].cb = cb;
timeout[i].arg = v;
numtimeouts++;
}
void Fl::remove_timeout(void (*cb)(void *), void *v) {
@ -105,22 +112,16 @@ void Fl::remove_timeout(void (*cb)(void *), void *v) {
}
static void call_timeouts() {
if (timeout[0].time > 0) return;
struct {
void (*cb)(void *);
void *arg;
} temp[MAXTIMEOUT];
int i,j,k;
// copy all expired timeouts to temp array:
for (i=j=0; j<numtimeouts && timeout[j].time <= 0; i++,j++) {
temp[i].cb = timeout[j].cb;
temp[i].arg= timeout[j].arg;
while (numtimeouts) {
if (timeout[0].time > 0) break;
// we must remove timeout from array before doing the callback:
void (*cb)(void*) = timeout[0].cb;
void *arg = timeout[0].arg;
numtimeouts--;
if (numtimeouts) memmove(timeout, timeout+1, numtimeouts*sizeof(Timeout));
// now it is safe for the callback to do add_timeout:
cb(arg);
}
// remove them from source array:
for (k=0; j<numtimeouts;) timeout[k++] = timeout[j++];
numtimeouts = k;
// and then call them:
for (k=0; k<i; k++) temp[k].cb(temp[k].arg);
}
void Fl::flush() {
@ -695,5 +696,5 @@ int fl_old_shortcut(const char* s) {
}
//
// End of "$Id: Fl.cxx,v 1.24.2.3 1999/04/10 08:09:38 bill Exp $".
// End of "$Id: Fl.cxx,v 1.24.2.4 1999/04/17 01:02:28 bill Exp $".
//

View File

@ -1,5 +1,5 @@
//
// "$Id: Fl_win32.cxx,v 1.33.2.5 1999/04/10 08:09:38 bill Exp $"
// "$Id: Fl_win32.cxx,v 1.33.2.6 1999/04/17 01:02:29 bill Exp $"
//
// WIN32-specific code for the Fast Light Tool Kit (FLTK).
//
@ -56,43 +56,60 @@
#define POLLIN 1
#define POLLOUT 4
#define POLLERR 8
struct pollfd {int fd; short events; short revents;};
#define MAXFD 8
static fd_set fdsets[3];
static int nfds;
static struct pollfd fds[MAXFD];
static struct {
static int nfds = 0;
static int fd_array_size = 0;
static struct FD {
int fd;
short events;
void (*cb)(int, void*);
void* arg;
} fd[MAXFD];
} *fd = 0;
void Fl::add_fd(int n, int events, void (*cb)(int, void*), void *v) {
int i;
if (nfds < MAXFD) {i = nfds; nfds++;} else {i = MAXFD-1;}
fds[i].fd = n;
fds[i].events = events;
remove_fd(n,events);
int i = nfds++;
if (i >= fd_array_size) {
fd_array_size = 2*fd_array_size+1;
fd = (FD*)realloc(fd, fd_array_size*sizeof(FD));
}
fd[i].fd = n;
fd[i].events = events;
fd[i].cb = cb;
fd[i].arg = v;
if (events & POLLIN) FD_SET(n, &fdsets[0]);
if (events & POLLOUT) FD_SET(n, &fdsets[1]);
if (events & POLLERR) FD_SET(n, &fdsets[2]);
fd[i].cb = cb;
fd[i].arg = v;
if (n > maxfd) maxfd = n;
}
void Fl::add_fd(int fd, void (*cb)(int, void*), void* v) {
Fl::add_fd(fd,POLLIN,cb,v);
Fl::add_fd(fd, POLLIN, cb, v);
}
void Fl::remove_fd(int n, int events) {
int i,j;
for (i=j=0; i<nfds; i++) {
if (fd[i].fd == n) {
int e = fd[i].events & ~events;
if (!e) continue; // if no events left, delete this fd
fd[i].events = e;
}
// move it down in the array if necessary:
if (j<i) {
fd[j]=fd[i];
}
j++;
}
nfds = j;
if (events & POLLIN) FD_CLR(n, &fdsets[0]);
if (events & POLLOUT) FD_CLR(n, &fdsets[1]);
if (events & POLLERR) FD_CLR(n, &fdsets[2]);
if (n == maxfd) maxfd--;
}
void Fl::remove_fd(int n) {
int i,j;
for (i=j=0; i<nfds; i++) {
if (fds[i].fd == n);
else {if (j<i) {fd[j]=fd[i]; fds[j]=fds[i];} j++;}
}
nfds = j;
FD_CLR(n, &fdsets[0]);
FD_CLR(n, &fdsets[1]);
FD_CLR(n, &fdsets[2]);
remove_fd(n, -1);
}
MSG fl_msg;
@ -112,29 +129,28 @@ int fl_ready() {
double fl_wait(int timeout_flag, double time) {
int have_message;
timeval t;
fd_set fdt[3];
if (nfds) {
// For WIN32 we need to poll for socket input FIRST, since
// the event queue is not something we can select() on...
timeval t;
t.tv_sec = 0;
t.tv_usec = 0;
fd_set fdt[3];
fdt[0] = fdsets[0];
fdt[1] = fdsets[1];
fdt[2] = fdsets[2];
// For WIN32 we need to poll for socket input FIRST, since
// the event queue is not something we can select() on...
t.tv_sec = 0;
t.tv_usec = 0;
fdt[0] = fdsets[0];
fdt[1] = fdsets[1];
fdt[2] = fdsets[2];
if (::select(0,&fdt[0],&fdt[1],&fdt[2],&t)) {
// We got something - do the callback!
for (int i = 0; i < nfds; i ++) {
int f = fds[i].fd;
short revents = 0;
if (FD_ISSET(f,&fdt[0])) revents |= POLLIN;
if (FD_ISSET(f,&fdt[1])) revents |= POLLOUT;
if (FD_ISSET(f,&fdt[2])) revents |= POLLERR;
if (fds[i].events & revents) fd[i].cb(f, fd[i].arg);
if (::select(0,&fdt[0],&fdt[1],&fdt[2],&t)) {
// We got something - do the callback!
for (int i = 0; i < nfds; i ++) {
int f = fd[i].fd;
short revents = 0;
if (FD_ISSET(f,&fdt[0])) revents |= POLLIN;
if (FD_ISSET(f,&fdt[1])) revents |= POLLOUT;
if (FD_ISSET(f,&fdt[2])) revents |= POLLERR;
if (fd[i].events & revents) fd[i].cb(f, fd[i].arg);
}
}
}
@ -905,5 +921,5 @@ void Fl_Window::make_current() {
}
//
// End of "$Id: Fl_win32.cxx,v 1.33.2.5 1999/04/10 08:09:38 bill Exp $".
// End of "$Id: Fl_win32.cxx,v 1.33.2.6 1999/04/17 01:02:29 bill Exp $".
//

View File

@ -1,5 +1,5 @@
//
// "$Id: Fl_x.cxx,v 1.24.2.2 1999/04/10 08:09:39 bill Exp $"
// "$Id: Fl_x.cxx,v 1.24.2.3 1999/04/17 01:02:29 bill Exp $"
//
// X specific code for the Fast Light Tool Kit (FLTK).
//
@ -41,77 +41,103 @@
#include <string.h>
#include <unistd.h>
#include <sys/time.h>
#if HAVE_SYS_SELECT_H
# include <sys/select.h>
#endif /* HAVE_SYS_SELECT_H */
////////////////////////////////////////////////////////////////
// interface to poll/select call:
#if HAVE_POLL
#include <poll.h>
static pollfd *pollfds = 0;
#else
struct pollfd {int fd; short events; short revents;};
#if HAVE_SYS_SELECT_H
# include <sys/select.h>
#endif /* HAVE_SYS_SELECT_H */
// The following #define is only needed for HP-UX 9.x and earlier:
//#define select(a,b,c,d,e) select((a),(int *)(b),(int *)(c),(int *)(d),(e))
static fd_set fdsets[3];
static int maxfd;
#define POLLIN 1
#define POLLOUT 4
#define POLLERR 8
//
// The following #define is only needed for HP-UX 9.x and earlier. 10.x
// and beyond have the right stuff, and any good GCC distribution fixes
// this, too!
//
#endif /* HAVE_POLL */
//#define select(a,b,c,d,e) select((a),(int *)(b),(int *)(c),(int *)(d),(e))
#endif
#define MAXFD 8
#if !HAVE_POLL
static fd_set fdsets[3];
static int maxfd;
#endif
static int nfds;
static struct pollfd fds[MAXFD];
static struct {
static int nfds = 0;
static int fd_array_size = 0;
static struct FD {
int fd;
short events;
void (*cb)(int, void*);
void* arg;
} fd[MAXFD];
} *fd = 0;
void Fl::add_fd(int n, int events, void (*cb)(int, void*), void *v) {
int i;
if (nfds < MAXFD) {i = nfds; nfds++;} else {i = MAXFD-1;}
remove_fd(n,events);
int i = nfds++;
if (i >= fd_array_size) {
fd_array_size = 2*fd_array_size+1;
fd = (FD*)realloc(fd, fd_array_size*sizeof(FD));
#if HAVE_POLL
pollfds = (pollfd*)realloc(pollfds, fd_array_size*sizeof(pollfd));
#endif
}
fd[i].fd = n;
fd[i].events = events;
fd[i].cb = cb;
fd[i].arg = v;
#if HAVE_POLL
fds[i].fd = n;
fds[i].events = events;
#if !HAVE_POLL
#else
if (events & POLLIN) FD_SET(n, &fdsets[0]);
if (events & POLLOUT) FD_SET(n, &fdsets[1]);
if (events & POLLERR) FD_SET(n, &fdsets[2]);
if (n > maxfd) maxfd = n;
#endif
fd[i].cb = cb;
fd[i].arg = v;
}
void Fl::add_fd(int fd, void (*cb)(int, void*), void* v) {
Fl::add_fd(fd,POLLIN,cb,v);
Fl::add_fd(fd, POLLIN, cb, v);
}
void Fl::remove_fd(int n) {
void Fl::remove_fd(int n, int events) {
int i,j;
for (i=j=0; i<nfds; i++) {
if (fds[i].fd == n);
else {if (j<i) {fd[j]=fd[i]; fds[j]=fds[i];} j++;}
if (fd[i].fd == n) {
int e = fd[i].events & ~events;
if (!e) continue; // if no events left, delete this fd
fd[i].events = e;
#if HAVE_POLL
fds[j].events = e;
#endif
}
// move it down in the array if necessary:
if (j<i) {
fd[j]=fd[i];
#if HAVE_POLL
fds[j]=fds[i];
#endif
}
j++;
}
nfds = j;
#if !HAVE_POLL
FD_CLR(n, &fdsets[0]);
FD_CLR(n, &fdsets[1]);
FD_CLR(n, &fdsets[2]);
if (events & POLLIN) FD_CLR(n, &fdsets[0]);
if (events & POLLOUT) FD_CLR(n, &fdsets[1]);
if (events & POLLERR) FD_CLR(n, &fdsets[2]);
if (n == maxfd) maxfd--;
#endif
}
void Fl::remove_fd(int n) {
remove_fd(n, -1);
}
int fl_ready() {
if (XQLength(fl_display)) return 1;
#if HAVE_POLL
@ -185,14 +211,14 @@ double fl_wait(int timeout_flag, double time) {
if (n > 0) {
for (int i=0; i<nfds; i++) {
#if HAVE_POLL
if (fds[i].revents) fd[i].cb(fds[i].fd, fd[i].arg);
if (fds[i].revents) fd[i].cb(fd[i].fd, fd[i].arg);
#else
int f = fds[i].fd;
int f = fd[i].fd;
short revents = 0;
if (FD_ISSET(f,&fdt[0])) revents |= POLLIN;
if (FD_ISSET(f,&fdt[1])) revents |= POLLOUT;
if (FD_ISSET(f,&fdt[2])) revents |= POLLERR;
if (fds[i].events & revents) fd[i].cb(f, fd[i].arg);
if (fd[i].events & revents) fd[i].cb(f, fd[i].arg);
#endif
}
}
@ -823,5 +849,5 @@ void Fl_Window::make_current() {
#endif
//
// End of "$Id: Fl_x.cxx,v 1.24.2.2 1999/04/10 08:09:39 bill Exp $".
// End of "$Id: Fl_x.cxx,v 1.24.2.3 1999/04/17 01:02:29 bill Exp $".
//

View File

@ -1,5 +1,5 @@
//
// "$Id: button.cxx,v 1.4 1999/01/07 19:17:50 mike Exp $"
// "$Id: button.cxx,v 1.4.2.1 1999/04/17 01:02:30 bill Exp $"
//
// Button/callback test program for the Fast Light Tool Kit (FLTK).
//
@ -37,6 +37,15 @@ void exitcb(Fl_Widget *, void *) {
exit(0);
}
#if 0
// test Fl::add_fd()...
void stdin_cb(int, void*) {
char buf[1000];
gets(buf);
printf("stdin callback\n");
}
#endif
int main(int argc, char ** argv) {
Fl_Window *window = new Fl_Window(320,65);
Fl_Button *b1 = new Fl_Button(20, 20, 80, 25, "&Beep");
@ -46,9 +55,12 @@ int main(int argc, char ** argv) {
b3->callback(exitcb,0);
window->end();
window->show(argc,argv);
#if 0
Fl::add_fd(0, stdin_cb);
#endif
return Fl::run();
}
//
// End of "$Id: button.cxx,v 1.4 1999/01/07 19:17:50 mike Exp $".
// End of "$Id: button.cxx,v 1.4.2.1 1999/04/17 01:02:30 bill Exp $".
//