You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@apr.apache.org by ji...@apache.org on 2009/10/03 01:28:52 UTC

svn commit: r821200 - in /apr/apr/branches/1.4.x/poll/unix: pollcb.c pollset.c

Author: jim
Date: Fri Oct  2 23:28:51 2009
New Revision: 821200

URL: http://svn.apache.org/viewvc?rev=821200&view=rev
Log:
Finish backport of poll changes from trunk.

Added:
    apr/apr/branches/1.4.x/poll/unix/pollcb.c   (with props)
    apr/apr/branches/1.4.x/poll/unix/pollset.c   (with props)

Added: apr/apr/branches/1.4.x/poll/unix/pollcb.c
URL: http://svn.apache.org/viewvc/apr/apr/branches/1.4.x/poll/unix/pollcb.c?rev=821200&view=auto
==============================================================================
--- apr/apr/branches/1.4.x/poll/unix/pollcb.c (added)
+++ apr/apr/branches/1.4.x/poll/unix/pollcb.c Fri Oct  2 23:28:51 2009
@@ -0,0 +1,166 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifdef WIN32
+/* POSIX defines 1024 for the FD_SETSIZE */
+#define FD_SETSIZE 1024
+#endif
+
+#include "apr.h"
+#include "apr_poll.h"
+#include "apr_time.h"
+#include "apr_portable.h"
+#include "apr_arch_file_io.h"
+#include "apr_arch_networkio.h"
+#include "apr_arch_poll_private.h"
+
+static apr_pollset_method_e pollset_default_method = POLLSET_DEFAULT_METHOD;
+#if defined(HAVE_KQUEUE)
+extern apr_pollcb_provider_t *apr_pollcb_provider_kqueue;
+#endif
+#if defined(HAVE_PORT_CREATE)
+extern apr_pollcb_provider_t *apr_pollcb_provider_port;
+#endif
+#if defined(HAVE_EPOLL)
+extern apr_pollcb_provider_t *apr_pollcb_provider_epoll;
+#endif
+#if defined(HAVE_POLL)
+extern apr_pollcb_provider_t *apr_pollcb_provider_poll;
+#endif
+
+static apr_pollcb_provider_t *pollcb_provider(apr_pollset_method_e method)
+{
+    apr_pollcb_provider_t *provider = NULL;
+    switch (method) {
+        case APR_POLLSET_KQUEUE:
+#if defined(HAVE_KQUEUE)
+            provider = apr_pollcb_provider_kqueue;
+#endif
+        break;
+        case APR_POLLSET_PORT:
+#if defined(HAVE_PORT_CREATE)
+            provider = apr_pollcb_provider_port;
+#endif
+        break;
+        case APR_POLLSET_EPOLL:
+#if defined(HAVE_EPOLL)
+            provider = apr_pollcb_provider_epoll;
+#endif
+        break;
+        case APR_POLLSET_POLL:
+#if defined(HAVE_POLL)
+            provider = apr_pollcb_provider_poll;
+#endif
+        break;
+        case APR_POLLSET_SELECT:
+        case APR_POLLSET_DEFAULT:
+        break;
+    }
+    return provider;
+}
+
+APR_DECLARE(apr_status_t) apr_pollcb_create_ex(apr_pollcb_t **pollcb,
+                                               apr_uint32_t size,
+                                               apr_pool_t *p,
+                                               apr_uint32_t flags,
+                                               apr_pollset_method_e method)
+{
+    apr_status_t rv;
+    apr_pollcb_provider_t *provider = NULL;
+
+    if (method == APR_POLLSET_DEFAULT)
+        method = pollset_default_method;
+    while (provider == NULL) {
+        provider = pollcb_provider(method);
+        if (!provider) {
+            *pollcb = NULL;
+            if ((flags & APR_POLLSET_NODEFAULT) == APR_POLLSET_NODEFAULT)
+                return APR_ENOTIMPL;
+            if (method == pollset_default_method)
+                return APR_ENOTIMPL;
+            method = pollset_default_method;
+        }
+    }
+
+    *pollcb = apr_palloc(p, sizeof(**pollcb));
+    (*pollcb)->nelts = 0;
+    (*pollcb)->nalloc = size;
+    (*pollcb)->pool = p;
+    (*pollcb)->provider = provider;
+
+    rv = (*provider->create)(*pollcb, size, p, flags);
+    if (rv == APR_ENOTIMPL) {
+        *pollcb = NULL;
+        if (method == pollset_default_method) {
+            return rv;
+        }
+
+        if ((flags & APR_POLLSET_NODEFAULT) == APR_POLLSET_NODEFAULT) {
+            return rv;
+        }
+
+        /* Try with default provider */
+        provider = pollcb_provider(pollset_default_method);
+        if (!provider) {
+            return APR_ENOTIMPL;
+        }
+        rv = (*provider->create)(*pollcb, size, p, flags);
+        if (rv != APR_SUCCESS) {
+            return rv;
+        }
+        (*pollcb)->provider = provider;
+    }
+
+    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)
+{
+    apr_pollset_method_e method = APR_POLLSET_DEFAULT;
+ #ifdef WIN32
+    /* This will work only if ws2_32.dll has WSAPoll funtion.
+     * We could check the presence of the function here,
+     * but someone might implement other pollcb method in
+     * the future.
+     */
+    method = APR_POLLSET_POLL;
+ #endif
+    return apr_pollcb_create_ex(pollcb, size, p, flags, method);
+}
+
+APR_DECLARE(apr_status_t) apr_pollcb_add(apr_pollcb_t *pollcb,
+                                         apr_pollfd_t *descriptor)
+{
+    return (*pollcb->provider->add)(pollcb, descriptor);
+}
+
+APR_DECLARE(apr_status_t) apr_pollcb_remove(apr_pollcb_t *pollcb,
+                                            apr_pollfd_t *descriptor)
+{
+    return (*pollcb->provider->remove)(pollcb, 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)
+{
+    return (*pollcb->provider->poll)(pollcb, timeout, func, baton);
+}

Propchange: apr/apr/branches/1.4.x/poll/unix/pollcb.c
------------------------------------------------------------------------------
    svn:eol-style = native

Added: apr/apr/branches/1.4.x/poll/unix/pollset.c
URL: http://svn.apache.org/viewvc/apr/apr/branches/1.4.x/poll/unix/pollset.c?rev=821200&view=auto
==============================================================================
--- apr/apr/branches/1.4.x/poll/unix/pollset.c (added)
+++ apr/apr/branches/1.4.x/poll/unix/pollset.c Fri Oct  2 23:28:51 2009
@@ -0,0 +1,347 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifdef WIN32
+/* POSIX defines 1024 for the FD_SETSIZE */
+#define FD_SETSIZE 1024
+#endif
+
+#include "apr.h"
+#include "apr_poll.h"
+#include "apr_time.h"
+#include "apr_portable.h"
+#include "apr_arch_file_io.h"
+#include "apr_arch_networkio.h"
+#include "apr_arch_poll_private.h"
+#include "apr_arch_inherit.h"
+
+static apr_pollset_method_e pollset_default_method = POLLSET_DEFAULT_METHOD;
+
+#if !APR_FILES_AS_SOCKETS
+#if defined (WIN32)
+
+extern apr_status_t
+apr_file_socket_pipe_create(apr_file_t **in,
+                            apr_file_t **out,
+                            apr_pool_t *p);
+
+extern apr_status_t
+apr_file_socket_pipe_close(apr_file_t *file);
+
+/* Create a dummy wakeup socket pipe for interrupting the poller
+ */
+static apr_status_t create_wakeup_pipe(apr_pollset_t *pollset)
+{
+    apr_status_t rv;
+    apr_pollfd_t fd;
+
+    if ((rv = apr_file_socket_pipe_create(&pollset->wakeup_pipe[0],
+                                          &pollset->wakeup_pipe[1],
+                                          pollset->pool)) != APR_SUCCESS)
+        return rv;
+    fd.reqevents = APR_POLLIN;
+    fd.desc_type = APR_POLL_FILE;
+    fd.desc.f = pollset->wakeup_pipe[0];
+    /* Add the pipe to the pollset
+     */
+    return apr_pollset_add(pollset, &fd);
+}
+
+#else  /* !WIN32 */
+static apr_status_t create_wakeup_pipe(apr_pollset_t *pollset)
+{
+    return APR_ENOTIMPL;
+}
+
+static apr_status_t apr_file_socket_pipe_close(apr_file_t *file)
+{
+    return APR_ENOTIMPL;
+}
+
+#endif /* WIN32 */
+#else  /* APR_FILES_AS_SOCKETS */
+
+/* Create a dummy wakeup pipe for interrupting the poller
+ */
+static apr_status_t create_wakeup_pipe(apr_pollset_t *pollset)
+{
+    apr_status_t rv;
+    apr_pollfd_t fd;
+
+    if ((rv = apr_file_pipe_create(&pollset->wakeup_pipe[0],
+                                   &pollset->wakeup_pipe[1],
+                                   pollset->pool)) != APR_SUCCESS)
+        return rv;
+    fd.reqevents = APR_POLLIN;
+    fd.desc_type = APR_POLL_FILE;
+    fd.desc.f = pollset->wakeup_pipe[0];
+
+    {
+        int flags;
+
+        if ((flags = fcntl(pollset->wakeup_pipe[0]->filedes, F_GETFD)) == -1)
+            return errno;
+
+        flags |= FD_CLOEXEC;
+        if (fcntl(pollset->wakeup_pipe[0]->filedes, F_SETFD, flags) == -1)
+            return errno;
+    }
+    {
+        int flags;
+
+        if ((flags = fcntl(pollset->wakeup_pipe[1]->filedes, F_GETFD)) == -1)
+            return errno;
+
+        flags |= FD_CLOEXEC;
+        if (fcntl(pollset->wakeup_pipe[1]->filedes, F_SETFD, flags) == -1)
+            return errno;
+    }
+
+    /* Add the pipe to the pollset
+     */
+    return apr_pollset_add(pollset, &fd);
+}
+#endif /* !APR_FILES_AS_SOCKETS */
+
+/* Read and discard what's ever in the wakeup pipe.
+ */
+void apr_pollset_drain_wakeup_pipe(apr_pollset_t *pollset)
+{
+    char rb[512];
+    apr_size_t nr = sizeof(rb);
+
+    while (apr_file_read(pollset->wakeup_pipe[0], rb, &nr) == APR_SUCCESS) {
+        /* Although we write just one byte to the other end of the pipe
+         * during wakeup, multiple treads could call the wakeup.
+         * So simply drain out from the input side of the pipe all
+         * the data.
+         */
+        if (nr != sizeof(rb))
+            break;
+    }
+}
+
+static apr_status_t pollset_cleanup(void *p)
+{
+    apr_pollset_t *pollset = (apr_pollset_t *) p;
+    if (pollset->provider->cleanup) {
+        (*pollset->provider->cleanup)(pollset);
+    }
+    if (pollset->flags & APR_POLLSET_WAKEABLE) {
+        /* Close both sides of the wakeup pipe */
+        if (pollset->wakeup_pipe[0]) {
+#if APR_FILES_AS_SOCKETS
+            apr_file_close(pollset->wakeup_pipe[0]);
+#else
+            apr_file_socket_pipe_close(pollset->wakeup_pipe[0]);
+#endif
+            pollset->wakeup_pipe[0] = NULL;
+        }
+        if (pollset->wakeup_pipe[1]) {
+#if APR_FILES_AS_SOCKETS
+            apr_file_close(pollset->wakeup_pipe[1]);
+#else
+            apr_file_socket_pipe_close(pollset->wakeup_pipe[1]);
+#endif
+            pollset->wakeup_pipe[1] = NULL;
+        }
+    }
+
+    return APR_SUCCESS;
+}
+
+#if defined(HAVE_KQUEUE)
+extern apr_pollset_provider_t *apr_pollset_provider_kqueue;
+#endif
+#if defined(HAVE_PORT_CREATE)
+extern apr_pollset_provider_t *apr_pollset_provider_port;
+#endif
+#if defined(HAVE_EPOLL)
+extern apr_pollset_provider_t *apr_pollset_provider_epoll;
+#endif
+#if defined(HAVE_POLL)
+extern apr_pollset_provider_t *apr_pollset_provider_poll;
+#endif
+extern apr_pollset_provider_t *apr_pollset_provider_select;
+
+static apr_pollset_provider_t *pollset_provider(apr_pollset_method_e method)
+{
+    apr_pollset_provider_t *provider = NULL;
+    switch (method) {
+        case APR_POLLSET_KQUEUE:
+#if defined(HAVE_KQUEUE)
+            provider = apr_pollset_provider_kqueue;
+#endif
+        break;
+        case APR_POLLSET_PORT:
+#if defined(HAVE_PORT_CREATE)
+            provider = apr_pollset_provider_port;
+#endif
+        break;
+        case APR_POLLSET_EPOLL:
+#if defined(HAVE_EPOLL)
+            provider = apr_pollset_provider_epoll;
+#endif
+        break;
+        case APR_POLLSET_POLL:
+#if defined(HAVE_POLL)
+            provider = apr_pollset_provider_poll;
+#endif
+        break;
+        case APR_POLLSET_SELECT:
+            provider = apr_pollset_provider_select;
+        break;
+        case APR_POLLSET_DEFAULT:
+        break;
+    }
+    return provider;
+}
+
+APR_DECLARE(apr_status_t) apr_pollset_create_ex(apr_pollset_t **pollset,
+                                                apr_uint32_t size,
+                                                apr_pool_t *p,
+                                                apr_uint32_t flags,
+                                                apr_pollset_method_e method)
+{
+    apr_status_t rv;
+    apr_pollset_provider_t *provider = NULL;
+
+    if (method == APR_POLLSET_DEFAULT)
+        method = pollset_default_method;
+    while (provider == NULL) {
+        provider = pollset_provider(method);
+        if (!provider) {
+            *pollset = NULL;
+            if ((flags & APR_POLLSET_NODEFAULT) == APR_POLLSET_NODEFAULT)
+                return APR_ENOTIMPL;
+            if (method == pollset_default_method)
+                return APR_ENOTIMPL;
+            method = pollset_default_method;
+        }
+    }
+    if (flags & APR_POLLSET_WAKEABLE) {
+        /* Add room for wakeup descriptor */
+        size++;
+    }
+
+    *pollset = apr_palloc(p, sizeof(**pollset));
+    (*pollset)->nelts = 0;
+    (*pollset)->nalloc = size;
+    (*pollset)->pool = p;
+    (*pollset)->flags = flags;
+    (*pollset)->provider = provider;
+
+    rv = (*provider->create)(*pollset, size, p, flags);
+    if (rv == APR_ENOTIMPL) {
+        if (method == pollset_default_method) {
+            *pollset = NULL;
+            return rv;
+        }
+        provider = pollset_provider(pollset_default_method);
+        if (!provider) {
+            *pollset = NULL;
+            return APR_ENOTIMPL;
+        }
+        rv = (*provider->create)(*pollset, size, p, flags);
+        if (rv != APR_SUCCESS) {
+            *pollset = NULL;
+            return rv;
+        }
+        (*pollset)->provider = provider;
+    }
+    if (flags & APR_POLLSET_WAKEABLE) {
+        /* Create wakeup pipe */
+        if ((rv = create_wakeup_pipe(*pollset)) != APR_SUCCESS) {
+            *pollset = NULL;
+            return rv;
+        }
+    }
+    if ((flags & APR_POLLSET_WAKEABLE) || provider->cleanup)
+        apr_pool_cleanup_register(p, *pollset, pollset_cleanup,
+                                  apr_pool_cleanup_null);
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(const char *) apr_pollset_method_name(apr_pollset_t *pollset)
+{
+    return pollset->provider->name;
+}
+
+APR_DECLARE(const char *) apr_poll_method_defname()
+{
+    apr_pollset_provider_t *provider = NULL;
+
+    provider = pollset_provider(pollset_default_method);
+    if (provider)
+        return provider->name;
+    else
+        return "unknown";
+}
+
+APR_DECLARE(apr_status_t) apr_pollset_create(apr_pollset_t **pollset,
+                                             apr_uint32_t size,
+                                             apr_pool_t *p,
+                                             apr_uint32_t flags)
+{
+    apr_pollset_method_e method = APR_POLLSET_DEFAULT;
+ #ifdef WIN32
+    /* Favor WSAPoll if supported.
+     * This will work only if ws2_32.dll has WSAPoll funtion.
+     * In other cases it will fall back to select() method unless
+     * the APR_POLLSET_NODEFAULT is added to the flags.
+     */
+    method = APR_POLLSET_POLL;
+ #endif
+    return apr_pollset_create_ex(pollset, size, p, flags, method);
+}
+
+APR_DECLARE(apr_status_t) apr_pollset_destroy(apr_pollset_t * pollset)
+{
+    if (pollset->flags & APR_POLLSET_WAKEABLE ||
+        pollset->provider->cleanup)
+        return apr_pool_cleanup_run(pollset->pool, pollset,
+                                    pollset_cleanup);
+    else
+        return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_pollset_wakeup(apr_pollset_t *pollset)
+{
+    if (pollset->flags & APR_POLLSET_WAKEABLE)
+        return apr_file_putc(1, pollset->wakeup_pipe[1]);
+    else
+        return APR_EINIT;
+}
+
+APR_DECLARE(apr_status_t) apr_pollset_add(apr_pollset_t *pollset,
+                                          const apr_pollfd_t *descriptor)
+{
+    return (*pollset->provider->add)(pollset, descriptor);
+}
+
+APR_DECLARE(apr_status_t) apr_pollset_remove(apr_pollset_t *pollset,
+                                             const apr_pollfd_t *descriptor)
+{
+    return (*pollset->provider->remove)(pollset, descriptor);
+}
+
+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)
+{
+    return (*pollset->provider->poll)(pollset, timeout, num, descriptors);
+}

Propchange: apr/apr/branches/1.4.x/poll/unix/pollset.c
------------------------------------------------------------------------------
    svn:eol-style = native