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 */