summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpquerna <pquerna@13f79535-47bb-0310-9956-ffa450edef68>2006-03-31 05:07:04 +0000
committerpquerna <pquerna@13f79535-47bb-0310-9956-ffa450edef68>2006-03-31 05:07:04 +0000
commit7d5f2b0770cc9e4420c492237c5a9e3738c5cc7a (patch)
tree14b64411b4888ade0dedb470ff9945cae0b05e47
parentb60b2e3ee2baaaed50b0f498dc17b2c33b44c547 (diff)
downloadlibapr-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.h20
-rw-r--r--poll/unix/epoll.c124
-rw-r--r--test/testpoll.c11
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;
}