The attached patch removes the double for() loops in both the KQueue
and epoll _poll() implementations. Both epoll and kqueue have a method
for associating arbitrary user data with the event. This patch uses
these to store the key to an event's location in the query_set array.
I also had to change testpoll.c again because the kqueue and epoll
implementations will return their result set with a different order (but
the same sockets will still come..)
Thanks,
-Paul Querna
Index: poll/unix/poll.c
===================================================================
RCS file: /home/cvspublic/apr/poll/unix/poll.c,v
retrieving revision 1.46
diff -u -r1.46 poll.c
--- poll/unix/poll.c 7 Jul 2004 07:40:12 -0000 1.46
+++ poll/unix/poll.c 18 Jul 2004 21:30:31 -0000
@@ -471,7 +471,8 @@
}
if (descriptor->reqevents & APR_POLLIN) {
- EV_SET(&pollset->kevent, fd, EVFILT_READ, EV_ADD, 0, 0, NULL);
+ EV_SET(&pollset->kevent, fd, EVFILT_READ, EV_ADD, 0, 0,
+ (void*)pollset->nelts);
if (kevent(pollset->kqueue_fd, &pollset->kevent, 1, NULL, 0,
NULL) == -1) {
@@ -480,7 +481,8 @@
}
if (descriptor->reqevents & APR_POLLOUT) {
- EV_SET(&pollset->kevent, fd, EVFILT_WRITE, EV_ADD, 0, 0, NULL);
+ EV_SET(&pollset->kevent, fd, EVFILT_WRITE, EV_ADD, 0, 0,
+ (void*)pollset->nelts);
if (kevent(pollset->kqueue_fd, &pollset->kevent, 1, NULL, 0,
NULL) == -1) {
@@ -490,16 +492,16 @@
#elif defined(HAVE_EPOLL)
ev.events = get_epoll_event(descriptor->reqevents);
+ ev.data.fd = pollset->nelts;
if (descriptor->desc_type == APR_POLL_SOCKET) {
- ev.data.fd = descriptor->desc.s->socketdes;
ret = epoll_ctl(pollset->epoll_fd, EPOLL_CTL_ADD,
descriptor->desc.s->socketdes, &ev);
}
else {
- ev.data.fd = descriptor->desc.f->filedes;
ret = epoll_ctl(pollset->epoll_fd, EPOLL_CTL_ADD,
descriptor->desc.f->filedes, &ev);
}
+
if (0 != ret) {
return APR_EBADF;
}
@@ -723,14 +725,15 @@
return APR_NOTFOUND;
}
+
#ifdef HAVE_KQUEUE
+
APR_DECLARE(apr_status_t) apr_pollset_poll(apr_pollset_t *pollset,
apr_interval_time_t timeout,
apr_int32_t *num,
const apr_pollfd_t **descriptors)
{
- int rv;
- apr_uint32_t i, j, r = 0;
+ int rv, i, r;
struct timespec tv, *tvptr;
if (timeout < 0) {
@@ -752,28 +755,16 @@
return APR_TIMEUP;
}
- /* TODO: Is there a better way to re-associate our data? */
- for (i = 0; i < pollset->nelts; i++) {
- apr_os_sock_t fd;
- if (pollset->query_set[i].desc_type == APR_POLL_SOCKET) {
- fd = pollset->query_set[i].desc.s->socketdes;
- }
- else {
- fd = pollset->query_set[i].desc.f->filedes;
- }
- for (j = 0; j < rv; j++) {
- if (pollset->ke_set[j].ident == fd ) {
- pollset->result_set[r] = pollset->query_set[i];
- pollset->result_set[r].rtnevents =
- get_kqueue_revent(pollset->ke_set[j].filter,
- pollset->ke_set[j].flags);
- r++;
- }
- }
+ r = 0;
+ for (i = 0; i < rv; i++) {
+ pollset->result_set[r] =
+ pollset->query_set[((int)pollset->ke_set[i].udata)];
+ pollset->result_set[r].rtnevents =
+ get_kqueue_revent(pollset->ke_set[i].filter,
+ pollset->ke_set[i].flags);
+ r++;
}
- (*num) = r;
-
if (descriptors) {
*descriptors = pollset->result_set;
}
@@ -788,8 +779,7 @@
apr_int32_t *num,
const apr_pollfd_t **descriptors)
{
- int rv;
- apr_uint32_t i, j, k;
+ int rv, i, r;
if (timeout > 0) {
timeout /= 1000;
@@ -804,38 +794,24 @@
if (rv == 0) {
return APR_TIMEUP;
}
- j = 0;
- for (i = 0; i < pollset->nelts; i++) {
- if (pollset->pollset[i].events != 0) {
- /* TODO: Is there a better way to re-associate our data? */
- for (k = 0; k < pollset->nelts; k++) {
- if (pollset->query_set[k].desc_type == APR_POLL_SOCKET &&
- pollset->query_set[k].desc.s->socketdes ==
- pollset->pollset[i].data.fd) {
- pollset->result_set[j] = pollset->query_set[k];
- pollset->result_set[j].rtnevents =
- get_epoll_revent(pollset->pollset[i].events);
- j++;
- break;
- }
- else if (pollset->query_set[k].desc_type == APR_POLL_FILE
- && pollset->query_set[k].desc.f->filedes ==
- pollset->pollset[i].data.fd) {
- pollset->result_set[j] = pollset->query_set[k];
- pollset->result_set[j].rtnevents =
- get_epoll_revent(pollset->pollset[i].events);
- j++;
- break;
- }
- }
- }
+
+ r = 0;
+ for (i = 0; i < rv; i++) {
+ pollset->result_set[r] =
+ pollset->query_set[pollset->pollset[i].data.fd];
+ pollset->result_set[r].rtnevents =
+ get_epoll_revent(pollset->pollset[i].events);
+ r++;
}
+
if (descriptors) {
*descriptors = pollset->result_set;
}
return APR_SUCCESS;
}
+
#elif defined(HAVE_POLL)
+
APR_DECLARE(apr_status_t) apr_pollset_poll(apr_pollset_t *pollset,
apr_interval_time_t timeout,
apr_int32_t *num,
Index: test/testpoll.c
===================================================================
RCS file: /home/cvspublic/apr/test/testpoll.c,v
retrieving revision 1.34
diff -u -r1.34 testpoll.c
--- test/testpoll.c 6 Jul 2004 03:38:06 -0000 1.34
+++ test/testpoll.c 18 Jul 2004 21:30:32 -0000
@@ -426,6 +426,7 @@
static void pollset_remove(abts_case *tc, void *data)
{
apr_status_t rv;
+ int i, c;
apr_pollset_t *pollset;
const apr_pollfd_t *hot_files;
apr_pollfd_t pfd;
@@ -472,13 +473,29 @@
rv = apr_pollset_poll(pollset, 1000, &num, &hot_files);
ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
ABTS_INT_EQUAL(tc, 3, num);
- ABTS_PTR_EQUAL(tc, (void *)1, hot_files[0].client_data);
- ABTS_PTR_EQUAL(tc, s[0], hot_files[0].desc.s);
- ABTS_PTR_EQUAL(tc, (void *)3, hot_files[1].client_data);
- ABTS_PTR_EQUAL(tc, s[2], hot_files[1].desc.s);
- ABTS_PTR_EQUAL(tc, (void *)4, hot_files[2].client_data);
- ABTS_PTR_EQUAL(tc, s[3], hot_files[2].desc.s);
-
+
+ for(i = 0, c = 0; i < num; i++) {
+ if(hot_files[i].client_data == (void*)1) {
+ ABTS_PTR_EQUAL(tc, (void *)1, hot_files[i].client_data);
+ ABTS_PTR_EQUAL(tc, s[0], hot_files[i].desc.s);
+ c++;
+ }
+ else if(hot_files[i].client_data == (void*)3) {
+ ABTS_PTR_EQUAL(tc, (void *)3, hot_files[i].client_data);
+ ABTS_PTR_EQUAL(tc, s[2], hot_files[i].desc.s);
+ c++;
+ }
+ else if(hot_files[i].client_data == (void*)4) {
+ ABTS_PTR_EQUAL(tc, (void *)4, hot_files[i].client_data);
+ ABTS_PTR_EQUAL(tc, s[3], hot_files[1].desc.s);
+ c++;
+ }
+ else {
+ ABTS_ASSERT(tc, "Client Data is Invalid.", 1);
+ }
+ }
+ ABTS_INT_EQUAL(tc, c, num);
+
/* now remove the pollset elements referring to desc s[2] */
pfd.desc.s = s[2];
pfd.client_data = (void *)999; /* not used on this call */