Moved poll handling to the generic part of the server objects.
Fixed busy waiting on POLLERR events.
Merged struct client into struct thread.
diff --git a/server/select.c b/server/select.c
index a1286cf..98b4817 100644
--- a/server/select.c
+++ b/server/select.c
@@ -19,12 +19,6 @@
#include "thread.h"
-struct poll_user
-{
- void (*func)(int event, void *private); /* callback function */
- void *private; /* callback private data */
-};
-
struct timeout_user
{
struct timeout_user *next; /* next in sorted timeout list */
@@ -34,32 +28,31 @@
void *private; /* callback private data */
};
-static struct poll_user *poll_users; /* users array */
+static struct object **poll_users; /* users array */
static struct pollfd *pollfd; /* poll fd array */
static int nb_users; /* count of array entries actually in use */
static int active_users; /* current number of active users */
static int allocated_users; /* count of allocated entries in the array */
-static struct poll_user *freelist; /* list of free entries in the array */
+static struct object **freelist; /* list of free entries in the array */
static struct timeout_user *timeout_head; /* sorted timeouts list head */
static struct timeout_user *timeout_tail; /* sorted timeouts list tail */
/* add a user and return an opaque handle to it, or -1 on failure */
-int add_select_user( int fd, void (*func)(int, void *), void *private )
+int add_select_user( struct object *obj )
{
int ret;
if (freelist)
{
ret = freelist - poll_users;
- freelist = poll_users[ret].private;
- assert( !poll_users[ret].func );
+ freelist = (struct object **)poll_users[ret];
}
else
{
if (nb_users == allocated_users)
{
- struct poll_user *newusers;
+ struct object **newusers;
struct pollfd *newpoll;
int new_count = allocated_users ? (allocated_users + allocated_users / 2) : 16;
if (!(newusers = realloc( poll_users, new_count * sizeof(*poll_users) ))) return -1;
@@ -74,43 +67,53 @@
}
ret = nb_users++;
}
- pollfd[ret].fd = fd;
+ pollfd[ret].fd = obj->fd;
pollfd[ret].events = 0;
pollfd[ret].revents = 0;
- poll_users[ret].func = func;
- poll_users[ret].private = private;
+ poll_users[ret] = obj;
+ obj->select = ret;
active_users++;
return ret;
}
-/* remove a user and close its fd */
-void remove_select_user( int user )
+/* remove an object from the select list and close its fd */
+void remove_select_user( struct object *obj )
{
- if (user == -1) return; /* avoids checking in all callers */
- assert( poll_users[user].func );
- close( pollfd[user].fd );
+ int user = obj->select;
+ assert( poll_users[user] == obj );
pollfd[user].fd = -1;
pollfd[user].events = 0;
pollfd[user].revents = 0;
- poll_users[user].func = NULL;
- poll_users[user].private = freelist;
+ poll_users[user] = (struct object *)freelist;
freelist = &poll_users[user];
+ close( obj->fd );
+ obj->fd = -1;
+ obj->select = -1;
active_users--;
}
-/* change the fd of a select user (the old fd is closed) */
-void change_select_fd( int user, int fd )
+/* change the fd of an object (the old fd is closed) */
+void change_select_fd( struct object *obj, int fd )
{
- assert( poll_users[user].func );
- close( pollfd[user].fd );
+ int user = obj->select;
+ assert( poll_users[user] == obj );
pollfd[user].fd = fd;
+ close( obj->fd );
+ obj->fd = fd;
}
/* set the events that select waits for on this fd */
-void set_select_events( int user, int events )
+void set_select_events( struct object *obj, int events )
{
- assert( poll_users[user].func );
- pollfd[user].events = events;
+ int user = obj->select;
+ assert( poll_users[user] == obj );
+ if (events == -1) /* stop waiting on this fd completely */
+ {
+ pollfd[user].fd = -1;
+ pollfd[user].events = 0;
+ pollfd[user].revents = 0;
+ }
+ else if (pollfd[user].fd != -1) pollfd[user].events = events;
}
/* check if events are pending */
@@ -259,7 +262,7 @@
{
if (pollfd[i].revents)
{
- poll_users[i].func( pollfd[i].revents, poll_users[i].private );
+ poll_users[i]->ops->poll_event( poll_users[i], pollfd[i].revents );
if (!--ret) break;
}
}