diff options
| author | pquerna <pquerna@13f79535-47bb-0310-9956-ffa450edef68> | 2006-03-31 05:07:04 +0000 |
|---|---|---|
| committer | pquerna <pquerna@13f79535-47bb-0310-9956-ffa450edef68> | 2006-03-31 05:07:04 +0000 |
| commit | 7d5f2b0770cc9e4420c492237c5a9e3738c5cc7a (patch) | |
| tree | 14b64411b4888ade0dedb470ff9945cae0b05e47 | |
| parent | b60b2e3ee2baaaed50b0f498dc17b2c33b44c547 (diff) | |
| download | libapr-7d5f2b0770cc9e4420c492237c5a9e3738c5cc7a.tar.gz | |
Add a first revision of the Pollset Callback API.
Currently it only has an EPoll implementation, and the most basic test case possible.
git-svn-id: http://svn.apache.org/repos/asf/apr/apr/branches/pollcb-dev@390326 13f79535-47bb-0310-9956-ffa450edef68
| -rw-r--r-- | include/apr_poll.h | 20 | ||||
| -rw-r--r-- | poll/unix/epoll.c | 124 | ||||
| -rw-r--r-- | test/testpoll.c | 11 |
3 files changed, 155 insertions, 0 deletions
diff --git a/include/apr_poll.h b/include/apr_poll.h index 601463e50..0a50d3db9 100644 --- a/include/apr_poll.h +++ b/include/apr_poll.h @@ -188,7 +188,27 @@ APR_DECLARE(apr_status_t) apr_poll(apr_pollfd_t *aprset, apr_int32_t numsock, /** @} */ +/** Opaque structure used for pollset API */ +typedef struct apr_pollcb_t apr_pollcb_t; + +APR_DECLARE(apr_status_t) apr_pollcb_create(apr_pollcb_t **pollcb, + apr_uint32_t size, + apr_pool_t *pool, + apr_uint32_t flags); + + +APR_DECLARE(apr_status_t) apr_pollcb_add(apr_pollcb_t *pollcb, + apr_pollfd_t *descriptor); + +APR_DECLARE(apr_status_t) apr_pollcb_remove(apr_pollcb_t *pollcb, + apr_pollfd_t *descriptor); + +typedef apr_status_t(*apr_pollcb_cb_t)(void* baton, apr_pollfd_t *descriptor); +APR_DECLARE(apr_status_t) apr_pollcb_poll(apr_pollcb_t *pollcb, + apr_interval_time_t timeout, + apr_pollcb_cb_t func, + void *baton); #ifdef __cplusplus } #endif diff --git a/poll/unix/epoll.c b/poll/unix/epoll.c index 8f921776c..0049a0c1c 100644 --- a/poll/unix/epoll.c +++ b/poll/unix/epoll.c @@ -296,4 +296,128 @@ APR_DECLARE(apr_status_t) apr_pollset_poll(apr_pollset_t *pollset, return rv; } +struct apr_pollcb_t { + apr_pool_t *pool; + apr_uint32_t nalloc; + struct epoll_event *pollset; + int epoll_fd; +}; + +static apr_status_t cb_cleanup(void *p_) +{ + apr_pollcb_t *pollcb = (apr_pollcb_t *) p_; + close(pollcb->epoll_fd); + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_pollcb_create(apr_pollcb_t **pollcb, + apr_uint32_t size, + apr_pool_t *p, + apr_uint32_t flags) +{ + int fd; + + fd = epoll_create(size); + + if (fd < 0) { + *pollcb = NULL; + return apr_get_netos_error(); + } + + *pollcb = apr_palloc(p, sizeof(**pollcb)); + (*pollcb)->nalloc = size; + (*pollcb)->pool = p; + (*pollcb)->epoll_fd = fd; + (*pollcb)->pollset = apr_palloc(p, size * sizeof(struct epoll_event)); + apr_pool_cleanup_register(p, *pollcb, cb_cleanup, cb_cleanup); + + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_pollcb_add(apr_pollcb_t *pollcb, + apr_pollfd_t *descriptor) +{ + struct epoll_event ev; + int ret; + + ev.events = get_epoll_event(descriptor->reqevents); + ev.data.ptr = (void *)descriptor; + + if (descriptor->desc_type == APR_POLL_SOCKET) { + ret = epoll_ctl(pollcb->epoll_fd, EPOLL_CTL_ADD, + descriptor->desc.s->socketdes, &ev); + } + else { + ret = epoll_ctl(pollcb->epoll_fd, EPOLL_CTL_ADD, + descriptor->desc.f->filedes, &ev); + } + + if (ret == -1) { + return apr_get_netos_error(); + } + + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_pollcb_remove(apr_pollcb_t *pollcb, + apr_pollfd_t *descriptor) +{ + apr_status_t rv = APR_SUCCESS; + struct epoll_event ev; + int ret = -1; + + ev.events = get_epoll_event(descriptor->reqevents); + + if (descriptor->desc_type == APR_POLL_SOCKET) { + ret = epoll_ctl(pollcb->epoll_fd, EPOLL_CTL_DEL, + descriptor->desc.s->socketdes, &ev); + } + else { + ret = epoll_ctl(pollcb->epoll_fd, EPOLL_CTL_DEL, + descriptor->desc.f->filedes, &ev); + } + + if (ret < 0) { + rv = APR_NOTFOUND; + } + + return rv; +} + + +APR_DECLARE(apr_status_t) apr_pollcb_poll(apr_pollcb_t *pollcb, + apr_interval_time_t timeout, + apr_pollcb_cb_t func, + void *baton) +{ + int ret, i; + apr_status_t rv = APR_SUCCESS; + + if (timeout > 0) { + timeout /= 1000; + } + + ret = epoll_wait(pollcb->epoll_fd, pollcb->pollset, pollcb->nalloc, + timeout); + if (ret < 0) { + rv = apr_get_netos_error(); + } + else if (ret == 0) { + rv = APR_TIMEUP; + } + else { + for (i = 0; i < ret; i++) { + apr_pollfd_t *pollfd = (apr_pollfd_t *)(pollcb->pollset[i].data.ptr); + pollfd->rtnevents = get_epoll_revent(pollcb->pollset[i].events); + + rv = func(baton, pollfd); + if (rv) { + return rv; + } + } + } + + return rv; +} + #endif /* POLLSET_USES_EPOLL */ diff --git a/test/testpoll.c b/test/testpoll.c index 3e166470c..3e7130def 100644 --- a/test/testpoll.c +++ b/test/testpoll.c @@ -32,6 +32,7 @@ static apr_socket_t *s[LARGE_NUM_SOCKETS]; static apr_sockaddr_t *sa[LARGE_NUM_SOCKETS]; static apr_pollset_t *pollset; +static apr_pollcb_t *pollcb; /* ###: tests surrounded by ifdef OLD_POLL_INTERFACE either need to be * converted to use the pollset interface or removed. */ @@ -552,6 +553,14 @@ static void pollset_remove(abts_case *tc, void *data) (hot_files[1].client_data == (void *)1))); } +static void setup_pollcb(abts_case *tc, void *data) +{ + apr_status_t rv; + rv = apr_pollcb_create(&pollcb, LARGE_NUM_SOCKETS, p, 0); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); +} + + abts_suite *testpoll(abts_suite *suite) { suite = ADD_SUITE(suite) @@ -586,6 +595,8 @@ abts_suite *testpoll(abts_suite *suite) abts_run_test(suite, close_all_sockets, NULL); + abts_run_test(suite, setup_pollcb, NULL); + return suite; } |
