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:24:57 UTC

svn commit: r821199 [1/2] - in /apr/apr/branches/1.4.x: ./ include/ include/arch/unix/ poll/os2/ poll/unix/

Author: jim
Date: Fri Oct  2 23:24:56 2009
New Revision: 821199

URL: http://svn.apache.org/viewvc?rev=821199&view=rev
Log:
Backport all poll changes from r734707 up to now
from trunk.

Modified:
    apr/apr/branches/1.4.x/CHANGES
    apr/apr/branches/1.4.x/NWGNUmakefile
    apr/apr/branches/1.4.x/apr.dsp
    apr/apr/branches/1.4.x/configure.in
    apr/apr/branches/1.4.x/include/apr_poll.h
    apr/apr/branches/1.4.x/include/arch/unix/apr_arch_poll_private.h
    apr/apr/branches/1.4.x/libapr.dsp
    apr/apr/branches/1.4.x/poll/os2/pollset.c
    apr/apr/branches/1.4.x/poll/unix/epoll.c
    apr/apr/branches/1.4.x/poll/unix/kqueue.c
    apr/apr/branches/1.4.x/poll/unix/poll.c
    apr/apr/branches/1.4.x/poll/unix/port.c
    apr/apr/branches/1.4.x/poll/unix/select.c

Modified: apr/apr/branches/1.4.x/CHANGES
URL: http://svn.apache.org/viewvc/apr/apr/branches/1.4.x/CHANGES?rev=821199&r1=821198&r2=821199&view=diff
==============================================================================
--- apr/apr/branches/1.4.x/CHANGES [utf-8] (original)
+++ apr/apr/branches/1.4.x/CHANGES [utf-8] Fri Oct  2 23:24:56 2009
@@ -1,6 +1,11 @@
                                                      -*- coding: utf-8 -*-
 Changes for APR 1.4.0
 
+ *) Make apr_pollset and apr_pollcb implementations using providers.
+    Added apr_pollset_create_ex and apr_pollcb_create_ex that allows
+    choosing non-default providers.
+    [Mladen Turk]
+
   *) apr_temp_dir_get() now checks the TMPDIR environment variable first,
      instead of third.  [Jim Jagielski]
 

Modified: apr/apr/branches/1.4.x/NWGNUmakefile
URL: http://svn.apache.org/viewvc/apr/apr/branches/1.4.x/NWGNUmakefile?rev=821199&r1=821198&r2=821199&view=diff
==============================================================================
--- apr/apr/branches/1.4.x/NWGNUmakefile (original)
+++ apr/apr/branches/1.4.x/NWGNUmakefile Fri Oct  2 23:24:56 2009
@@ -311,6 +311,8 @@
 	$(OBJDIR)/rand.o \
 	$(OBJDIR)/readwrite.o \
 	$(OBJDIR)/seek.o \
+	$(OBJDIR)/pollcb.o \
+	$(OBJDIR)/pollset.o \
 	$(OBJDIR)/select.o \
 	$(OBJDIR)/sendrecv.o \
 	$(OBJDIR)/sha2.o \

Modified: apr/apr/branches/1.4.x/apr.dsp
URL: http://svn.apache.org/viewvc/apr/apr/branches/1.4.x/apr.dsp?rev=821199&r1=821198&r2=821199&view=diff
==============================================================================
--- apr/apr/branches/1.4.x/apr.dsp (original)
+++ apr/apr/branches/1.4.x/apr.dsp Fri Oct  2 23:24:56 2009
@@ -412,6 +412,14 @@
 # PROP Default_Filter ""
 # Begin Source File
 
+SOURCE=.\poll\unix\pollcb.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\poll\unix\pollset.c
+# End Source File
+# Begin Source File
+
 SOURCE=.\poll\unix\select.c
 # End Source File
 # End Group

Modified: apr/apr/branches/1.4.x/configure.in
URL: http://svn.apache.org/viewvc/apr/apr/branches/1.4.x/configure.in?rev=821199&r1=821198&r2=821199&view=diff
==============================================================================
--- apr/apr/branches/1.4.x/configure.in (original)
+++ apr/apr/branches/1.4.x/configure.in Fri Oct  2 23:24:56 2009
@@ -903,6 +903,128 @@
 dnl ----------------------------- Checking for fdatasync: OS X doesn't have it
 AC_CHECK_FUNCS(fdatasync)
 
+dnl ----------------------------- Checking for extended file descriptor handling
+# test for epoll_create1
+AC_CACHE_CHECK([for epoll_create1 support], [apr_cv_epoll_create1],
+[AC_TRY_RUN([
+#include <sys/epoll.h>
+#include <unistd.h>
+
+int main()
+{
+    return epoll_create1(0) == -1;
+}], [apr_cv_epoll_create1=yes], [apr_cv_epoll_create1=no], [apr_cv_epoll_create1=no])])
+
+if test "$apr_cv_epoll_create1" = "yes"; then
+   AC_DEFINE([HAVE_EPOLL_CREATE1], 1, [Define if epoll_create1 function is supported])
+fi
+
+# test for dup3
+AC_CACHE_CHECK([for dup3 support], [apr_cv_dup3],
+[AC_TRY_RUN([
+#include <unistd.h>
+
+int main()
+{
+    return dup3(STDOUT_FILENO, STDERR_FILENO, 0) == -1;
+}], [apr_cv_dup3=yes], [apr_cv_dup3=no], [apr_cv_dup3=no])])
+
+if test "$apr_cv_dup3" = "yes"; then
+   AC_DEFINE([HAVE_DUP3], 1, [Define if dup3 function is supported])
+fi
+
+# test for accept4
+AC_CACHE_CHECK([for accept4 support], [apr_cv_accept4],
+[AC_TRY_RUN([
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/wait.h>
+#include <signal.h>
+#include <errno.h>
+
+#define A4_SOCK "./apr_accept4_test_socket"
+
+int main()
+{
+    pid_t pid;
+    int fd;
+    struct sockaddr_un loc, rem;
+    socklen_t rem_sz;
+
+    if ((pid = fork())) {
+        int status;
+
+        unlink(A4_SOCK);
+
+        if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
+            goto cleanup_failure2;
+
+        loc.sun_family = AF_UNIX;
+        strncpy(loc.sun_path, A4_SOCK, sizeof(loc.sun_path) - 1);
+
+        if (bind(fd, (struct sockaddr *) &loc,
+                 sizeof(struct sockaddr_un)) == -1)
+            goto cleanup_failure;
+
+        if (listen(fd, 5) == -1)
+            goto cleanup_failure;
+
+        rem_sz = sizeof(struct sockaddr_un);
+        if (accept4(fd, (struct sockaddr *) &rem, &rem_sz, 0) == -1) {
+            goto cleanup_failure;
+        }
+        else {
+            close(fd);
+            waitpid(pid, &status, 0);
+            unlink(A4_SOCK);
+            return 0;
+        }
+
+cleanup_failure:
+        close(fd);
+cleanup_failure2:
+        kill(pid, SIGKILL);
+        waitpid(pid, &status, 0);
+        unlink(A4_SOCK);
+        return 1;
+    }
+    else {
+        if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
+            return 1; /* this will be bad: we'll hang */
+
+        loc.sun_family = AF_UNIX;
+        strncpy(loc.sun_path, A4_SOCK, sizeof(loc.sun_path) - 1);
+
+        while(connect(fd, (struct sockaddr *) &loc,
+                      sizeof(struct sockaddr_un)) == -1 &&
+              (errno==ENOENT || errno==ECONNREFUSED))
+            ;
+
+        close(fd);
+        return 0;
+    }
+}], [apr_cv_accept4=yes], [apr_cv_accept4=no], [apr_cv_accept4=no])])
+
+if test "$apr_cv_accept4" = "yes"; then
+   AC_DEFINE([HAVE_ACCEPT4], 1, [Define if accept4 function is supported])
+fi
+
+AC_CACHE_CHECK([for SOCK_CLOEXEC support], [apr_cv_sock_cloexec],
+[AC_TRY_RUN([
+#include <sys/types.h>
+#include <sys/socket.h>
+
+int main()
+{
+    return socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC, 0) == -1;
+}], [apr_cv_sock_cloexec=yes], [apr_cv_sock_cloexec=no], [apr_cv_sock_cloexec=no])])
+
+if test "$apr_cv_sock_cloexec" = "yes"; then
+   AC_DEFINE([HAVE_SOCK_CLOEXEC], 1, [Define if the SOCK_CLOEXEC flag is supported])
+fi
+
 dnl ----------------------------- Checking for missing POSIX thread functions
 AC_CHECK_FUNCS([getpwnam_r getpwuid_r getgrnam_r getgrgid_r])
 

Modified: apr/apr/branches/1.4.x/include/apr_poll.h
URL: http://svn.apache.org/viewvc/apr/apr/branches/1.4.x/include/apr_poll.h?rev=821199&r1=821198&r2=821199&view=diff
==============================================================================
--- apr/apr/branches/1.4.x/include/apr_poll.h (original)
+++ apr/apr/branches/1.4.x/include/apr_poll.h Fri Oct  2 23:24:56 2009
@@ -49,14 +49,36 @@
 #define APR_POLLOUT   0x004     /**< Can write without blocking */
 #define APR_POLLERR   0x010     /**< Pending error */
 #define APR_POLLHUP   0x020     /**< Hangup occurred */
-#define APR_POLLNVAL  0x040     /**< Descriptior invalid */
+#define APR_POLLNVAL  0x040     /**< Descriptor invalid */
 
 /**
  * Pollset Flags
  */
-#define APR_POLLSET_THREADSAFE 0x001 /**< Adding or Removing a Descriptor is thread safe */
-#define APR_POLLSET_NOCOPY     0x002 /**< Descriptors passed to apr_pollset_create() are not copied */
-#define APR_POLLSET_WAKEABLE   0x004 /**< Pollset poll operation is interruptable */
+#define APR_POLLSET_THREADSAFE 0x001 /**< Adding or removing a descriptor is
+                                      * thread-safe
+                                      */
+#define APR_POLLSET_NOCOPY     0x002 /**< Descriptors passed to apr_pollset_add()
+                                      * are not copied
+                                      */
+#define APR_POLLSET_WAKEABLE   0x004 /**< Poll operations are interruptable by
+                                      * apr_pollset_wakeup()
+                                      */
+#define APR_POLLSET_NODEFAULT  0x010 /**< Do not try to use the default method if
+                                      * the specified non-default method cannot be
+                                      * used
+                                      */
+
+/**
+ * Pollset Methods
+ */
+typedef enum {
+    APR_POLLSET_DEFAULT,        /**< Platform default poll method */
+    APR_POLLSET_SELECT,         /**< Poll uses select method */
+    APR_POLLSET_KQUEUE,
+    APR_POLLSET_PORT,
+    APR_POLLSET_EPOLL,
+    APR_POLLSET_POLL
+} apr_pollset_method_e;
 
 /** Used in apr_pollfd_t to determine what the apr_descriptor is */
 typedef enum { 
@@ -94,24 +116,27 @@
 typedef struct apr_pollset_t apr_pollset_t;
 
 /**
- * Setup a pollset object
+ * Set up a pollset object
  * @param pollset  The pointer in which to return the newly created object 
  * @param size The maximum number of descriptors that this pollset can hold
  * @param p The pool from which to allocate the pollset
  * @param flags Optional flags to modify the operation of the pollset.
  *
- * @remark If flags equals APR_POLLSET_THREADSAFE, then a pollset is
+ * @remark If flags contains APR_POLLSET_THREADSAFE, then a pollset is
  *         created on which it is safe to make concurrent calls to
  *         apr_pollset_add(), apr_pollset_remove() and apr_pollset_poll()
  *         from separate threads.  This feature is only supported on some
  *         platforms; the apr_pollset_create() call will fail with
  *         APR_ENOTIMPL on platforms where it is not supported.
- * @remark If flags contain APR_POLLSET_WAKEABLE, then a pollset is
- *         created with additional internal pipe object used for
+ * @remark If flags contains APR_POLLSET_WAKEABLE, then a pollset is
+ *         created with an additional internal pipe object used for the
  *         apr_pollset_wakeup() call. The actual size of pollset is
  *         in that case size + 1. This feature is only supported on some
  *         platforms; the apr_pollset_create() call will fail with
  *         APR_ENOTIMPL on platforms where it is not supported.
+ * @remark If flags contains APR_POLLSET_NOCOPY, then the apr_pollfd_t
+ *         structures passed to apr_pollset_add() are not copied and
+ *         must have a lifetime at least as long as the pollset.
  */
 APR_DECLARE(apr_status_t) apr_pollset_create(apr_pollset_t **pollset,
                                              apr_uint32_t size,
@@ -119,6 +144,38 @@
                                              apr_uint32_t flags);
 
 /**
+ * Set up a pollset object
+ * @param pollset  The pointer in which to return the newly created object 
+ * @param size The maximum number of descriptors that this pollset can hold
+ * @param p The pool from which to allocate the pollset
+ * @param flags Optional flags to modify the operation of the pollset.
+ * @param method Poll method to use. See @apr_pollset_method_e.  If this
+ *         method cannot be used, the default method will be used unless the
+ *         APR_POLLSET_NODEFAULT flag has been specified.
+ *
+ * @remark If flags contains APR_POLLSET_THREADSAFE, then a pollset is
+ *         created on which it is safe to make concurrent calls to
+ *         apr_pollset_add(), apr_pollset_remove() and apr_pollset_poll()
+ *         from separate threads.  This feature is only supported on some
+ *         platforms; the apr_pollset_create_ex() call will fail with
+ *         APR_ENOTIMPL on platforms where it is not supported.
+ * @remark If flags contains APR_POLLSET_WAKEABLE, then a pollset is
+ *         created with additional internal pipe object used for the
+ *         apr_pollset_wakeup() call. The actual size of pollset is
+ *         in that case size + 1. This feature is only supported on some
+ *         platforms; the apr_pollset_create_ex() call will fail with
+ *         APR_ENOTIMPL on platforms where it is not supported.
+ * @remark If flags contains APR_POLLSET_NOCOPY, then the apr_pollfd_t
+ *         structures passed to apr_pollset_add() are not copied and
+ *         must have a lifetime at least as long as the pollset.
+ */
+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);
+
+/**
  * Destroy a pollset object
  * @param pollset The pollset to destroy
  */
@@ -140,6 +197,15 @@
  *         with APR_EINTR.  Option (1) is recommended, but option (2) is
  *         allowed for implementations where option (1) is impossible
  *         or impractical.
+ * @remark If the pollset has been created with APR_POLLSET_NOCOPY, the 
+ *         apr_pollfd_t structure referenced by descriptor will not be copied
+ *         and must have a lifetime at least as long as the pollset.
+ * @remark Do not add the same socket or file descriptor to the same pollset
+ *         multiple times, even if the requested events differ for the 
+ *         different calls to apr_pollset_add().  If the events of interest
+ *         for a descriptor change, you must first remove the descriptor 
+ *         from the pollset with apr_pollset_remove(), then add it again 
+ *         specifying all requested events.
  */
 APR_DECLARE(apr_status_t) apr_pollset_add(apr_pollset_t *pollset,
                                           const apr_pollfd_t *descriptor);
@@ -157,6 +223,9 @@
  *         with APR_EINTR.  Option (1) is recommended, but option (2) is
  *         allowed for implementations where option (1) is impossible
  *         or impractical.
+ * @remark apr_pollset_remove() cannot be used to remove a subset of requested
+ *         events for a descriptor.  The reqevents field in the apr_pollfd_t
+ *         parameter must contain the same value when removing as when adding.
  */
 APR_DECLARE(apr_status_t) apr_pollset_remove(apr_pollset_t *pollset,
                                              const apr_pollfd_t *descriptor);
@@ -164,16 +233,20 @@
 /**
  * Block for activity on the descriptor(s) in a pollset
  * @param pollset The pollset to use
- * @param timeout The amount of time in microseconds to wait.  This is 
- *                a maximum, not a minimum.  If a descriptor is signalled, we 
- *                will wake up before this time.  A negative number means 
- *                wait until a descriptor is signalled.
+ * @param timeout The amount of time in microseconds to wait.  This is a
+ *                maximum, not a minimum.  If a descriptor is signalled, the
+ *                function will return before this time.  If timeout is
+ *                negative, the function will block until a descriptor is
+ *                signalled or until apr_pollset_wakeup() has been called.
  * @param num Number of signalled descriptors (output parameter)
  * @param descriptors Array of signalled descriptors (output parameter)
- * @remark If the pollset has been created with APR_POLLSET_WAKEABLE
- *         and the wakeup has been called while waiting for activity
- *         return value is APR_EINTR in case there was no signaled
- *         descriptors at the time of wakeup call.
+ * @remark APR_EINTR will be returned if the pollset has been created with
+ *         APR_POLLSET_WAKEABLE, apr_pollset_wakeup() has been called while
+ *         waiting for activity, and there were no signalled descriptors at the
+ *         time of the wakeup call.
+ * @remark Multiple signalled conditions for the same descriptor may be reported
+ *         in one or more returned apr_pollfd_t structures, depending on the
+ *         implementation.
  */
 APR_DECLARE(apr_status_t) apr_pollset_poll(apr_pollset_t *pollset,
                                            apr_interval_time_t timeout,
@@ -181,7 +254,7 @@
                                            const apr_pollfd_t **descriptors);
 
 /**
- * Interrupt the blocked apr_pollset_poll call.
+ * Interrupt the blocked apr_pollset_poll() call.
  * @param pollset The pollset to use
  * @remark If the pollset was not created with APR_POLLSET_WAKEABLE the
  *         return value is APR_EINIT.
@@ -193,13 +266,14 @@
  * @param aprset The poll structure we will be using. 
  * @param numsock The number of descriptors we are polling
  * @param nsds The number of descriptors signalled (output parameter)
- * @param timeout The amount of time in microseconds to wait.  This is 
- *                a maximum, not a minimum.  If a descriptor is signalled, we 
- *                will wake up before this time.  A negative number means 
- *                wait until a descriptor is signalled.
+ * @param timeout The amount of time in microseconds to wait.  This is a
+ *                maximum, not a minimum.  If a descriptor is signalled, the
+ *                function will return before this time.  If timeout is
+ *                negative, the function will block until a descriptor is
+ *                signalled or until apr_pollset_wakeup() has been called.
  * @remark The number of descriptors signalled is returned in the third argument. 
  *         This is a blocking call, and it will not return until either a 
- *         descriptor has been signalled, or the timeout has expired. 
+ *         descriptor has been signalled or the timeout has expired. 
  * @remark The rtnevents field in the apr_pollfd_t array will only be filled-
  *         in if the return value is APR_SUCCESS.
  */
@@ -207,11 +281,23 @@
                                    apr_int32_t *nsds, 
                                    apr_interval_time_t timeout);
 
+/**
+ * Return a printable representation of the pollset method.
+ * @param pollset The pollset to use
+ */
+APR_DECLARE(const char *) apr_pollset_method_name(apr_pollset_t *pollset);
+
+/**
+ * Return a printable representation of the default pollset method
+ * (APR_POLLSET_DEFAULT).
+ */
+APR_DECLARE(const char *) apr_poll_method_defname(void);
+
 /** Opaque structure used for pollset API */
 typedef struct apr_pollcb_t apr_pollcb_t;
 
 /**
- * Setup a pollcb object
+ * Set up a pollcb object
  * @param pollcb  The pointer in which to return the newly created object 
  * @param size The maximum number of descriptors that a single _poll can return.
  * @param p The pool from which to allocate the pollcb
@@ -226,15 +312,40 @@
                                             apr_uint32_t flags);
 
 /**
+ * Set up a pollcb object
+ * @param pollcb  The pointer in which to return the newly created object 
+ * @param size The maximum number of descriptors that a single _poll can return.
+ * @param p The pool from which to allocate the pollcb
+ * @param flags Optional flags to modify the operation of the pollcb.
+ * @param method Poll method to use. See @apr_pollset_method_e.  If this
+ *         method cannot be used, the default method will be used unless the
+ *         APR_POLLSET_NODEFAULT flag has been specified.
+ *
+ * @remark Pollcb is only supported on some platforms; the apr_pollcb_create_ex()
+ * call will fail with APR_ENOTIMPL on platforms where it is not supported.
+ */
+APR_DECLARE(apr_status_t) apr_pollcb_create_ex(apr_pollcb_t **pollcb,
+                                               apr_uint32_t size,
+                                               apr_pool_t *pool,
+                                               apr_uint32_t flags,
+                                               apr_pollset_method_e method);
+
+/**
  * Add a socket or file descriptor to a pollcb
  * @param pollcb The pollcb to which to add the descriptor
  * @param descriptor The descriptor to add
- * @remark If you set client_data in the descriptor, that value
- *         will be returned in the client_data field whenever this
- *         descriptor is signalled in apr_pollcb_poll().
+ * @remark If you set client_data in the descriptor, that value will be
+ *         returned in the client_data field whenever this descriptor is
+ *         signalled in apr_pollcb_poll().
  * @remark Unlike the apr_pollset API, the descriptor is not copied, and users 
- *         must retain the memory used by descriptor, as the same pointer will be 
- *         returned to them from apr_pollcb_poll.
+ *         must retain the memory used by descriptor, as the same pointer will
+ *         be returned to them from apr_pollcb_poll.
+ * @remark Do not add the same socket or file descriptor to the same pollcb
+ *         multiple times, even if the requested events differ for the 
+ *         different calls to apr_pollcb_add().  If the events of interest
+ *         for a descriptor change, you must first remove the descriptor 
+ *         from the pollcb with apr_pollcb_remove(), then add it again 
+ *         specifying all requested events.
  */
 APR_DECLARE(apr_status_t) apr_pollcb_add(apr_pollcb_t *pollcb,
                                          apr_pollfd_t *descriptor);
@@ -242,6 +353,9 @@
  * Remove a descriptor from a pollcb
  * @param pollcb The pollcb from which to remove the descriptor
  * @param descriptor The descriptor to remove
+ * @remark apr_pollcb_remove() cannot be used to remove a subset of requested
+ *         events for a descriptor.  The reqevents field in the apr_pollfd_t
+ *         parameter must contain the same value when removing as when adding.
  */
 APR_DECLARE(apr_status_t) apr_pollcb_remove(apr_pollcb_t *pollcb,
                                             apr_pollfd_t *descriptor);
@@ -257,12 +371,16 @@
 /**
  * Block for activity on the descriptor(s) in a pollcb
  * @param pollcb The pollcb to use
- * @param timeout The amount of time in microseconds to wait.  This is 
- *                a maximum, not a minimum.  If a descriptor is signalled, we 
- *                will wake up before this time.  A negative number means 
- *                wait until a descriptor is signalled.
- * @param func Callback function to call for each active socket
+ * @param timeout The amount of time in microseconds to wait.  This is a
+ *                maximum, not a minimum.  If a descriptor is signalled, the
+ *                function will return before this time.  If timeout is
+ *                negative, the function will block until a descriptor is
+ *                signalled.
+ * @param func Callback function to call for each active descriptor.
  * @param baton Opaque baton passed to the callback function.
+ * @remark Multiple signalled conditions for the same descriptor may be reported
+ *         in one or more calls to the callback function, depending on the
+ *         implementation.
  */
 APR_DECLARE(apr_status_t) apr_pollcb_poll(apr_pollcb_t *pollcb,
                                           apr_interval_time_t timeout,

Modified: apr/apr/branches/1.4.x/include/arch/unix/apr_arch_poll_private.h
URL: http://svn.apache.org/viewvc/apr/apr/branches/1.4.x/include/arch/unix/apr_arch_poll_private.h?rev=821199&r1=821198&r2=821199&view=diff
==============================================================================
--- apr/apr/branches/1.4.x/include/arch/unix/apr_arch_poll_private.h (original)
+++ apr/apr/branches/1.4.x/include/arch/unix/apr_arch_poll_private.h Fri Oct  2 23:24:56 2009
@@ -17,13 +17,6 @@
 #ifndef APR_ARCH_POLL_PRIVATE_H
 #define APR_ARCH_POLL_PRIVATE_H
 
-#include "apr.h"
-#include "apr_poll.h"
-#include "apr_time.h"
-#include "apr_portable.h"
-#include "apr_arch_networkio.h"
-#include "apr_arch_file_io.h"
-
 #if HAVE_POLL_H
 #include <poll.h>
 #endif
@@ -55,21 +48,32 @@
 /* Choose the best method platform specific to use in apr_pollset */
 #ifdef HAVE_KQUEUE
 #define POLLSET_USES_KQUEUE
+#define POLLSET_DEFAULT_METHOD APR_POLLSET_KQUEUE
 #elif defined(HAVE_PORT_CREATE)
 #define POLLSET_USES_PORT
+#define POLLSET_DEFAULT_METHOD APR_POLLSET_PORT
 #elif defined(HAVE_EPOLL)
 #define POLLSET_USES_EPOLL
+#define POLLSET_DEFAULT_METHOD APR_POLLSET_EPOLL
 #elif defined(HAVE_POLL)
 #define POLLSET_USES_POLL
+#define POLLSET_DEFAULT_METHOD APR_POLLSET_POLL
 #else
 #define POLLSET_USES_SELECT
+#define POLLSET_DEFAULT_METHOD APR_POLLSET_SELECT
 #endif
 
+#ifdef WIN32
+#define POLL_USES_SELECT
+#undef POLLSET_DEFAULT_METHOD
+#define POLLSET_DEFAULT_METHOD APR_POLLSET_SELECT
+#else
 #ifdef HAVE_POLL
 #define POLL_USES_POLL
 #else
 #define POLL_USES_SELECT
 #endif
+#endif
 
 #if defined(POLLSET_USES_KQUEUE) || defined(POLLSET_USES_EPOLL) || defined(POLLSET_USES_PORT)
 
@@ -79,10 +83,10 @@
 #include "apr_thread_mutex.h"
 #define pollset_lock_rings() \
     if (pollset->flags & APR_POLLSET_THREADSAFE) \
-        apr_thread_mutex_lock(pollset->ring_lock);
+        apr_thread_mutex_lock(pollset->p->ring_lock);
 #define pollset_unlock_rings() \
     if (pollset->flags & APR_POLLSET_THREADSAFE) \
-        apr_thread_mutex_unlock(pollset->ring_lock);
+        apr_thread_mutex_unlock(pollset->p->ring_lock);
 #else
 #define pollset_lock_rings()
 #define pollset_unlock_rings()
@@ -93,8 +97,72 @@
 struct pfd_elem_t {
     APR_RING_ENTRY(pfd_elem_t) link;
     apr_pollfd_t pfd;
+#ifdef HAVE_PORT_CREATE
+   int on_query_ring;
+#endif
 };
 
 #endif
 
+typedef struct apr_pollset_private_t apr_pollset_private_t;
+typedef struct apr_pollset_provider_t apr_pollset_provider_t;
+typedef struct apr_pollcb_provider_t apr_pollcb_provider_t;
+struct apr_pollset_t
+{
+    apr_pool_t *pool;
+    apr_uint32_t nelts;
+    apr_uint32_t nalloc;
+    apr_uint32_t flags;
+    /* Pipe descriptors used for wakeup */
+    apr_file_t *wakeup_pipe[2];
+    apr_pollset_private_t *p;
+    apr_pollset_provider_t *provider;
+};
+
+typedef union {
+#if defined(HAVE_EPOLL)
+    struct epoll_event *epoll;
+#endif
+#if defined(HAVE_PORT_CREATE)
+    port_event_t *port;
+#endif
+#if defined(HAVE_KQUEUE)
+    struct kevent *ke;
+#endif
+#if defined(HAVE_POLL)
+    struct pollfd *ps;
+#endif
+    void *undef;
+} apr_pollcb_pset;
+
+struct apr_pollcb_t {
+    apr_pool_t *pool;
+    apr_uint32_t nelts;
+    apr_uint32_t nalloc;
+    int fd;
+    apr_pollcb_pset pollset;
+    apr_pollfd_t **copyset;
+    apr_pollcb_provider_t *provider;
+};
+
+struct apr_pollset_provider_t {
+    apr_status_t (*create)(apr_pollset_t *, apr_uint32_t, apr_pool_t *, apr_uint32_t);
+    apr_status_t (*add)(apr_pollset_t *, const apr_pollfd_t *);
+    apr_status_t (*remove)(apr_pollset_t *, const apr_pollfd_t *);
+    apr_status_t (*poll)(apr_pollset_t *, apr_interval_time_t, apr_int32_t *, const apr_pollfd_t **);
+    apr_status_t (*cleanup)(apr_pollset_t *);
+    const char *name;
+};
+
+struct apr_pollcb_provider_t {
+    apr_status_t (*create)(apr_pollcb_t *, apr_uint32_t, apr_pool_t *, apr_uint32_t);
+    apr_status_t (*add)(apr_pollcb_t *, apr_pollfd_t *);
+    apr_status_t (*remove)(apr_pollcb_t *, apr_pollfd_t *);
+    apr_status_t (*poll)(apr_pollcb_t *, apr_interval_time_t, apr_pollcb_cb_t, void *);
+    const char *name;
+};
+
+/* Private functions */
+void apr_pollset_drain_wakeup_pipe(apr_pollset_t *pollset);
+
 #endif /* APR_ARCH_POLL_PRIVATE_H */

Modified: apr/apr/branches/1.4.x/libapr.dsp
URL: http://svn.apache.org/viewvc/apr/apr/branches/1.4.x/libapr.dsp?rev=821199&r1=821198&r2=821199&view=diff
==============================================================================
--- apr/apr/branches/1.4.x/libapr.dsp (original)
+++ apr/apr/branches/1.4.x/libapr.dsp Fri Oct  2 23:24:56 2009
@@ -464,6 +464,14 @@
 # PROP Default_Filter ""
 # Begin Source File
 
+SOURCE=.\poll\unix\pollcb.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\poll\unix\pollset.c
+# End Source File
+# Begin Source File
+
 SOURCE=.\poll\unix\select.c
 # End Source File
 # End Group

Modified: apr/apr/branches/1.4.x/poll/os2/pollset.c
URL: http://svn.apache.org/viewvc/apr/apr/branches/1.4.x/poll/os2/pollset.c?rev=821199&r1=821198&r2=821199&view=diff
==============================================================================
--- apr/apr/branches/1.4.x/poll/os2/pollset.c (original)
+++ apr/apr/branches/1.4.x/poll/os2/pollset.c Fri Oct  2 23:24:56 2009
@@ -51,7 +51,14 @@
     return APR_SUCCESS;
 }
 
-
+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)
+{
+    return apr_pollset_create(pollset, size, p, flags);
+}
 
 APR_DECLARE(apr_status_t) apr_pollset_destroy(apr_pollset_t *pollset)
 {

Modified: apr/apr/branches/1.4.x/poll/unix/epoll.c
URL: http://svn.apache.org/viewvc/apr/apr/branches/1.4.x/poll/unix/epoll.c?rev=821199&r1=821198&r2=821199&view=diff
==============================================================================
--- apr/apr/branches/1.4.x/poll/unix/epoll.c (original)
+++ apr/apr/branches/1.4.x/poll/unix/epoll.c Fri Oct  2 23:24:56 2009
@@ -14,10 +14,16 @@
  * limitations under the License.
  */
 
+#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"
 
-#ifdef POLLSET_USES_EPOLL
+#if defined(HAVE_EPOLL)
 
 static apr_int16_t get_epoll_event(apr_int16_t event)
 {
@@ -29,11 +35,7 @@
         rv |= EPOLLPRI;
     if (event & APR_POLLOUT)
         rv |= EPOLLOUT;
-    if (event & APR_POLLERR)
-        rv |= EPOLLERR;
-    if (event & APR_POLLHUP)
-        rv |= EPOLLHUP;
-    /* APR_POLLNVAL is not handled by epoll. */
+    /* APR_POLLNVAL is not handled by epoll.  EPOLLERR and EPOLLHUP are return-only */
 
     return rv;
 }
@@ -57,17 +59,11 @@
     return rv;
 }
 
-struct apr_pollset_t
+struct apr_pollset_private_t
 {
-    apr_pool_t *pool;
-    apr_uint32_t nelts;
-    apr_uint32_t nalloc;
     int epoll_fd;
     struct epoll_event *pollset;
     apr_pollfd_t *result_set;
-    apr_uint32_t flags;
-    /* Pipe descriptors used for wakeup */
-    apr_file_t *wakeup_pipe[2];
 #if APR_HAS_THREADS
     /* A thread mutex to protect operations on the rings */
     apr_thread_mutex_t *ring_lock;
@@ -81,81 +77,29 @@
     APR_RING_HEAD(pfd_dead_ring_t, pfd_elem_t) dead_ring;
 };
 
-static apr_status_t backend_cleanup(void *p_)
+static apr_status_t impl_pollset_cleanup(apr_pollset_t *pollset)
 {
-    apr_pollset_t *pollset = (apr_pollset_t *) p_;
-    close(pollset->epoll_fd);
-    if (pollset->flags & APR_POLLSET_WAKEABLE) {
-        /* Close both sides of the wakeup pipe */
-        if (pollset->wakeup_pipe[0]) {
-            apr_file_close(pollset->wakeup_pipe[0]);
-            pollset->wakeup_pipe[0] = NULL;
-        }
-        if (pollset->wakeup_pipe[1]) {
-            apr_file_close(pollset->wakeup_pipe[1]);
-            pollset->wakeup_pipe[1] = NULL;
-        }
-    }
+    close(pollset->p->epoll_fd);
     return APR_SUCCESS;
 }
 
-/* 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];
-    /* Add the pipe to the pollset
-     */
-    return apr_pollset_add(pollset, &fd);
-}
-
-/* Read and discard what's ever in the wakeup pipe.
- */
-static void 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;
-    }
-}
 
-APR_DECLARE(apr_status_t) apr_pollset_create(apr_pollset_t **pollset,
-                                             apr_uint32_t size,
-                                             apr_pool_t *p,
-                                             apr_uint32_t flags)
+static apr_status_t impl_pollset_create(apr_pollset_t *pollset,
+                                        apr_uint32_t size,
+                                        apr_pool_t *p,
+                                        apr_uint32_t flags)
 {
     apr_status_t rv;
     int fd;
 
-    if (flags & APR_POLLSET_WAKEABLE) {
-        /* Add room for wakeup descriptor */
-        size++;
-    }
 #ifdef HAVE_EPOLL_CREATE1
     fd = epoll_create1(EPOLL_CLOEXEC);
 #else
     fd = epoll_create(size);
 #endif
     if (fd < 0) {
-        *pollset = NULL;
-        return errno;
+        pollset->p = NULL;
+        return apr_get_netos_error();
     }
 
 #ifndef HAVE_EPOLL_CREATE1
@@ -171,54 +115,36 @@
     }
 #endif
 
-    *pollset = apr_palloc(p, sizeof(**pollset));
+    pollset->p = apr_palloc(p, sizeof(apr_pollset_private_t));
 #if APR_HAS_THREADS
     if ((flags & APR_POLLSET_THREADSAFE) &&
         !(flags & APR_POLLSET_NOCOPY) &&
-        ((rv = apr_thread_mutex_create(&(*pollset)->ring_lock,
+        ((rv = apr_thread_mutex_create(&pollset->p->ring_lock,
                                        APR_THREAD_MUTEX_DEFAULT,
                                        p)) != APR_SUCCESS)) {
-        *pollset = NULL;
+        pollset->p = NULL;
         return rv;
     }
 #else
     if (flags & APR_POLLSET_THREADSAFE) {
-        *pollset = NULL;
+        pollset->p = NULL;
         return APR_ENOTIMPL;
     }
 #endif
-    (*pollset)->nelts = 0;
-    (*pollset)->nalloc = size;
-    (*pollset)->flags = flags;
-    (*pollset)->pool = p;
-    (*pollset)->epoll_fd = fd;
-    (*pollset)->pollset = apr_palloc(p, size * sizeof(struct epoll_event));
-    (*pollset)->result_set = apr_palloc(p, size * sizeof(apr_pollfd_t));
+    pollset->p->epoll_fd = fd;
+    pollset->p->pollset = apr_palloc(p, size * sizeof(struct epoll_event));
+    pollset->p->result_set = apr_palloc(p, size * sizeof(apr_pollfd_t));
 
     if (!(flags & APR_POLLSET_NOCOPY)) {
-        APR_RING_INIT(&(*pollset)->query_ring, pfd_elem_t, link);
-        APR_RING_INIT(&(*pollset)->free_ring, pfd_elem_t, link);
-        APR_RING_INIT(&(*pollset)->dead_ring, pfd_elem_t, link);
-    }
-    if (flags & APR_POLLSET_WAKEABLE) {
-        /* Create wakeup pipe */
-        if ((rv = create_wakeup_pipe(*pollset)) != APR_SUCCESS) {
-            close(fd);
-            *pollset = NULL;
-            return rv;
-        }
+        APR_RING_INIT(&pollset->p->query_ring, pfd_elem_t, link);
+        APR_RING_INIT(&pollset->p->free_ring, pfd_elem_t, link);
+        APR_RING_INIT(&pollset->p->dead_ring, pfd_elem_t, link);
     }
-    apr_pool_cleanup_register(p, *pollset, backend_cleanup, backend_cleanup);
     return APR_SUCCESS;
 }
 
-APR_DECLARE(apr_status_t) apr_pollset_destroy(apr_pollset_t *pollset)
-{
-    return apr_pool_cleanup_run(pollset->pool, pollset, backend_cleanup);
-}
-
-APR_DECLARE(apr_status_t) apr_pollset_add(apr_pollset_t *pollset,
-                                          const apr_pollfd_t *descriptor)
+static apr_status_t impl_pollset_add(apr_pollset_t *pollset,
+                                     const apr_pollfd_t *descriptor)
 {
     struct epoll_event ev = {0};
     int ret = -1;
@@ -233,8 +159,8 @@
     else {
         pollset_lock_rings();
 
-        if (!APR_RING_EMPTY(&(pollset->free_ring), pfd_elem_t, link)) {
-            elem = APR_RING_FIRST(&(pollset->free_ring));
+        if (!APR_RING_EMPTY(&(pollset->p->free_ring), pfd_elem_t, link)) {
+            elem = APR_RING_FIRST(&(pollset->p->free_ring));
             APR_RING_REMOVE(elem, link);
         }
         else {
@@ -245,27 +171,24 @@
         ev.data.ptr = elem;
     }
     if (descriptor->desc_type == APR_POLL_SOCKET) {
-        ret = epoll_ctl(pollset->epoll_fd, EPOLL_CTL_ADD,
+        ret = epoll_ctl(pollset->p->epoll_fd, EPOLL_CTL_ADD,
                         descriptor->desc.s->socketdes, &ev);
     }
     else {
-        ret = epoll_ctl(pollset->epoll_fd, EPOLL_CTL_ADD,
+        ret = epoll_ctl(pollset->p->epoll_fd, EPOLL_CTL_ADD,
                         descriptor->desc.f->filedes, &ev);
     }
 
-    if (pollset->flags & APR_POLLSET_NOCOPY) {
-        if (0 != ret) {
-            rv = APR_EBADF;
-        }
+    if (0 != ret) {
+        rv = apr_get_netos_error();
     }
-    else {
-        if (0 != ret) {
-            rv = APR_EBADF;
-            APR_RING_INSERT_TAIL(&(pollset->free_ring), elem, pfd_elem_t, link);
+
+    if (!(pollset->flags & APR_POLLSET_NOCOPY)) {
+        if (rv != APR_SUCCESS) {
+            APR_RING_INSERT_TAIL(&(pollset->p->free_ring), elem, pfd_elem_t, link);
         }
         else {
-            pollset->nelts++;
-            APR_RING_INSERT_TAIL(&(pollset->query_ring), elem, pfd_elem_t, link);
+            APR_RING_INSERT_TAIL(&(pollset->p->query_ring), elem, pfd_elem_t, link);
         }
         pollset_unlock_rings();
     }
@@ -273,22 +196,22 @@
     return rv;
 }
 
-APR_DECLARE(apr_status_t) apr_pollset_remove(apr_pollset_t *pollset,
-                                             const apr_pollfd_t *descriptor)
+static apr_status_t impl_pollset_remove(apr_pollset_t *pollset,
+                                        const apr_pollfd_t *descriptor)
 {
     pfd_elem_t *ep;
     apr_status_t rv = APR_SUCCESS;
-    struct epoll_event ev;
+    struct epoll_event ev = {0}; /* ignored, but must be passed with
+                                  * kernel < 2.6.9
+                                  */
     int ret = -1;
 
-    ev.events = get_epoll_event(descriptor->reqevents);
-
     if (descriptor->desc_type == APR_POLL_SOCKET) {
-        ret = epoll_ctl(pollset->epoll_fd, EPOLL_CTL_DEL,
+        ret = epoll_ctl(pollset->p->epoll_fd, EPOLL_CTL_DEL,
                         descriptor->desc.s->socketdes, &ev);
     }
     else {
-        ret = epoll_ctl(pollset->epoll_fd, EPOLL_CTL_DEL,
+        ret = epoll_ctl(pollset->p->epoll_fd, EPOLL_CTL_DEL,
                         descriptor->desc.f->filedes, &ev);
     }
     if (ret < 0) {
@@ -298,18 +221,16 @@
     if (!(pollset->flags & APR_POLLSET_NOCOPY)) {
         pollset_lock_rings();
 
-        if (!APR_RING_EMPTY(&(pollset->query_ring), pfd_elem_t, link)) {
-            for (ep = APR_RING_FIRST(&(pollset->query_ring));
-                 ep != APR_RING_SENTINEL(&(pollset->query_ring),
-                                         pfd_elem_t, link);
-                 ep = APR_RING_NEXT(ep, link)) {
+        for (ep = APR_RING_FIRST(&(pollset->p->query_ring));
+             ep != APR_RING_SENTINEL(&(pollset->p->query_ring),
+                                     pfd_elem_t, link);
+             ep = APR_RING_NEXT(ep, link)) {
                 
-                if (descriptor->desc.s == ep->pfd.desc.s) {
-                    APR_RING_REMOVE(ep, link);
-                    APR_RING_INSERT_TAIL(&(pollset->dead_ring),
-                                         ep, pfd_elem_t, link);
-                    break;
-                }
+            if (descriptor->desc.s == ep->pfd.desc.s) {
+                APR_RING_REMOVE(ep, link);
+                APR_RING_INSERT_TAIL(&(pollset->p->dead_ring),
+                                     ep, pfd_elem_t, link);
+                break;
             }
         }
 
@@ -319,20 +240,20 @@
     return rv;
 }
 
-APR_DECLARE(apr_status_t) apr_pollset_poll(apr_pollset_t *pollset,
+static apr_status_t impl_pollset_poll(apr_pollset_t *pollset,
                                            apr_interval_time_t timeout,
                                            apr_int32_t *num,
                                            const apr_pollfd_t **descriptors)
 {
     int ret, i, j;
     apr_status_t rv = APR_SUCCESS;
-    apr_pollfd_t fd;
+    apr_pollfd_t *fdptr;
 
     if (timeout > 0) {
         timeout /= 1000;
     }
 
-    ret = epoll_wait(pollset->epoll_fd, pollset->pollset, pollset->nalloc,
+    ret = epoll_wait(pollset->p->epoll_fd, pollset->p->pollset, pollset->nalloc,
                      timeout);
     (*num) = ret;
 
@@ -343,58 +264,43 @@
         rv = APR_TIMEUP;
     }
     else {
-        if (pollset->flags & APR_POLLSET_NOCOPY) {
-            for (i = 0, j = 0; i < ret; i++) {
-                fd = *((apr_pollfd_t *) (pollset->pollset[i].data.ptr));
-               /* Check if the polled descriptor is our
-                 * wakeup pipe. In that case do not put it result set.
-                 */
-                if ((pollset->flags & APR_POLLSET_WAKEABLE) &&
-                    fd.desc_type == APR_POLL_FILE &&
-                    fd.desc.f == pollset->wakeup_pipe[0]) {
-                        drain_wakeup_pipe(pollset);
-                        rv = APR_EINTR;
-                }
-                else {
-                    pollset->result_set[j] = fd;
-                    pollset->result_set[j].rtnevents =
-                        get_epoll_revent(pollset->pollset[i].events);
-                    j++;
-                }
+        for (i = 0, j = 0; i < ret; i++) {
+            if (pollset->flags & APR_POLLSET_NOCOPY) {
+                fdptr = (apr_pollfd_t *)(pollset->p->pollset[i].data.ptr);
             }
-            if (((*num) = j))
-                rv = APR_SUCCESS;
-        }
-        else {
-            for (i = 0, j = 0; i < ret; i++) {
-                fd = (((pfd_elem_t *) (pollset->pollset[i].data.ptr))->pfd);
-                if ((pollset->flags & APR_POLLSET_WAKEABLE) &&
-                    fd.desc_type == APR_POLL_FILE &&
-                    fd.desc.f == pollset->wakeup_pipe[0]) {
-                        drain_wakeup_pipe(pollset);
-                        rv = APR_EINTR;
-                }
-                else {
-                    pollset->result_set[j] = fd;
-                    pollset->result_set[j].rtnevents =
-                        get_epoll_revent(pollset->pollset[i].events);
-                    j++;
-                }
+            else {
+                fdptr = &(((pfd_elem_t *) (pollset->p->pollset[i].data.ptr))->pfd);
+            }
+            /* Check if the polled descriptor is our
+             * wakeup pipe. In that case do not put it result set.
+             */
+            if ((pollset->flags & APR_POLLSET_WAKEABLE) &&
+                fdptr->desc_type == APR_POLL_FILE &&
+                fdptr->desc.f == pollset->wakeup_pipe[0]) {
+                apr_pollset_drain_wakeup_pipe(pollset);
+                rv = APR_EINTR;
+            }
+            else {
+                pollset->p->result_set[j] = *fdptr;
+                pollset->p->result_set[j].rtnevents =
+                    get_epoll_revent(pollset->p->pollset[i].events);
+                j++;
             }
-            if (((*num) = j))
-                rv = APR_SUCCESS;
         }
+        if (((*num) = j)) { /* any event besides wakeup pipe? */
+            rv = APR_SUCCESS;
 
-        if (descriptors) {
-            *descriptors = pollset->result_set;
+            if (descriptors) {
+                *descriptors = pollset->p->result_set;
+            }
         }
     }
 
     if (!(pollset->flags & APR_POLLSET_NOCOPY)) {
         pollset_lock_rings();
 
-        /* Shift all PFDs in the Dead Ring to be Free Ring */
-        APR_RING_CONCAT(&(pollset->free_ring), &(pollset->dead_ring), pfd_elem_t, link);
+        /* Shift all PFDs in the Dead Ring to the Free Ring */
+        APR_RING_CONCAT(&(pollset->p->free_ring), &(pollset->p->dead_ring), pfd_elem_t, link);
 
         pollset_unlock_rings();
     }
@@ -402,32 +308,28 @@
     return rv;
 }
 
-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;
-}
-
-struct apr_pollcb_t {
-    apr_pool_t *pool;
-    apr_uint32_t nalloc;
-    struct epoll_event *pollset;
-    int epoll_fd;
+static apr_pollset_provider_t impl = {
+    impl_pollset_create,
+    impl_pollset_add,
+    impl_pollset_remove,
+    impl_pollset_poll,
+    impl_pollset_cleanup,
+    "epoll"
 };
 
+apr_pollset_provider_t *apr_pollset_provider_epoll = &impl;
+
 static apr_status_t cb_cleanup(void *p_)
 {
     apr_pollcb_t *pollcb = (apr_pollcb_t *) p_;
-    close(pollcb->epoll_fd);
+    close(pollcb->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)
+static apr_status_t impl_pollcb_create(apr_pollcb_t *pollcb,
+                                       apr_uint32_t size,
+                                       apr_pool_t *p,
+                                       apr_uint32_t flags)
 {
     int fd;
     
@@ -438,7 +340,6 @@
 #endif
     
     if (fd < 0) {
-        *pollcb = NULL;
         return apr_get_netos_error();
     }
 
@@ -455,18 +356,15 @@
     }
 #endif
     
-    *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);
+    pollcb->fd = fd;
+    pollcb->pollset.epoll = apr_palloc(p, size * sizeof(struct epoll_event));
+    apr_pool_cleanup_register(p, pollcb, cb_cleanup, apr_pool_cleanup_null);
 
     return APR_SUCCESS;
 }
 
-APR_DECLARE(apr_status_t) apr_pollcb_add(apr_pollcb_t *pollcb,
-                                         apr_pollfd_t *descriptor)
+static apr_status_t impl_pollcb_add(apr_pollcb_t *pollcb,
+                                    apr_pollfd_t *descriptor)
 {
     struct epoll_event ev;
     int ret;
@@ -475,11 +373,11 @@
     ev.data.ptr = (void *)descriptor;
 
     if (descriptor->desc_type == APR_POLL_SOCKET) {
-        ret = epoll_ctl(pollcb->epoll_fd, EPOLL_CTL_ADD,
+        ret = epoll_ctl(pollcb->fd, EPOLL_CTL_ADD,
                         descriptor->desc.s->socketdes, &ev);
     }
     else {
-        ret = epoll_ctl(pollcb->epoll_fd, EPOLL_CTL_ADD,
+        ret = epoll_ctl(pollcb->fd, EPOLL_CTL_ADD,
                         descriptor->desc.f->filedes, &ev);
     }
     
@@ -490,21 +388,21 @@
     return APR_SUCCESS;
 }
 
-APR_DECLARE(apr_status_t) apr_pollcb_remove(apr_pollcb_t *pollcb,
-                                            apr_pollfd_t *descriptor)
+static apr_status_t impl_pollcb_remove(apr_pollcb_t *pollcb,
+                                       apr_pollfd_t *descriptor)
 {
     apr_status_t rv = APR_SUCCESS;
-    struct epoll_event ev;
+    struct epoll_event ev = {0}; /* ignored, but must be passed with
+                                  * kernel < 2.6.9
+                                  */
     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,
+        ret = epoll_ctl(pollcb->fd, EPOLL_CTL_DEL,
                         descriptor->desc.s->socketdes, &ev);
     }
     else {
-        ret = epoll_ctl(pollcb->epoll_fd, EPOLL_CTL_DEL,
+        ret = epoll_ctl(pollcb->fd, EPOLL_CTL_DEL,
                         descriptor->desc.f->filedes, &ev);
     }
     
@@ -516,10 +414,10 @@
 }
 
 
-APR_DECLARE(apr_status_t) apr_pollcb_poll(apr_pollcb_t *pollcb,
-                                          apr_interval_time_t timeout,
-                                          apr_pollcb_cb_t func,
-                                          void *baton)
+static apr_status_t impl_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;
@@ -528,7 +426,7 @@
         timeout /= 1000;
     }
     
-    ret = epoll_wait(pollcb->epoll_fd, pollcb->pollset, pollcb->nalloc,
+    ret = epoll_wait(pollcb->fd, pollcb->pollset.epoll, pollcb->nalloc,
                      timeout);
     if (ret < 0) {
         rv = apr_get_netos_error();
@@ -538,8 +436,8 @@
     }
     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);
+            apr_pollfd_t *pollfd = (apr_pollfd_t *)(pollcb->pollset.epoll[i].data.ptr);
+            pollfd->rtnevents = get_epoll_revent(pollcb->pollset.epoll[i].events);
 
             rv = func(baton, pollfd);
             if (rv) {
@@ -551,4 +449,14 @@
     return rv;
 }
 
-#endif /* POLLSET_USES_EPOLL */
+static apr_pollcb_provider_t impl_cb = {
+    impl_pollcb_create,
+    impl_pollcb_add,
+    impl_pollcb_remove,
+    impl_pollcb_poll,
+    "epoll"
+};
+
+apr_pollcb_provider_t *apr_pollcb_provider_epoll = &impl_cb;
+
+#endif /* HAVE_EPOLL */

Modified: apr/apr/branches/1.4.x/poll/unix/kqueue.c
URL: http://svn.apache.org/viewvc/apr/apr/branches/1.4.x/poll/unix/kqueue.c?rev=821199&r1=821198&r2=821199&view=diff
==============================================================================
--- apr/apr/branches/1.4.x/poll/unix/kqueue.c (original)
+++ apr/apr/branches/1.4.x/poll/unix/kqueue.c Fri Oct  2 23:24:56 2009
@@ -14,10 +14,16 @@
  * limitations under the License.
  */
 
+#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"
 
-#ifdef POLLSET_USES_KQUEUE
+#ifdef HAVE_KQUEUE
 
 static apr_int16_t get_kqueue_revent(apr_int16_t event, apr_int16_t flags)
 {
@@ -25,28 +31,25 @@
 
     if (event == EVFILT_READ)
         rv |= APR_POLLIN;
-    if (event == EVFILT_WRITE)
+    else if (event == EVFILT_WRITE)
         rv |= APR_POLLOUT;
     if (flags & EV_EOF)
         rv |= APR_POLLHUP;
-    if (flags & EV_ERROR)
-        rv |= APR_POLLERR;
-
+    /* APR_POLLPRI, APR_POLLERR, and APR_POLLNVAL are not handled by this
+     * implementation.
+     * TODO: See if EV_ERROR + certain system errors in the returned data field
+     * should map to APR_POLLNVAL.
+     */
     return rv;
 }
 
-struct apr_pollset_t
+struct apr_pollset_private_t
 {
-    apr_pool_t *pool;
-    apr_uint32_t nelts;
-    apr_uint32_t nalloc;
     int kqueue_fd;
     struct kevent kevent;
+    apr_uint32_t setsize;
     struct kevent *ke_set;
     apr_pollfd_t *result_set;
-    apr_uint32_t flags;
-    /* Pipe descriptors used for wakeup */
-    apr_file_t *wakeup_pipe[2];
 #if APR_HAS_THREADS
     /* A thread mutex to protect operations on the rings */
     apr_thread_mutex_t *ring_lock;
@@ -60,140 +63,77 @@
     APR_RING_HEAD(pfd_dead_ring_t, pfd_elem_t) dead_ring;
 };
 
-static apr_status_t backend_cleanup(void *p_)
+static apr_status_t impl_pollset_cleanup(apr_pollset_t *pollset)
 {
-    apr_pollset_t *pollset = (apr_pollset_t *) p_;
-    close(pollset->kqueue_fd);
-    if (pollset->flags & APR_POLLSET_WAKEABLE) {
-        /* Close both sides of the wakeup pipe */
-        if (pollset->wakeup_pipe[0]) {
-            apr_file_close(pollset->wakeup_pipe[0]);
-            pollset->wakeup_pipe[0] = NULL;
-        }
-        if (pollset->wakeup_pipe[1]) {
-            apr_file_close(pollset->wakeup_pipe[1]);
-            pollset->wakeup_pipe[1] = NULL;
-        }
-    }
+    close(pollset->p->kqueue_fd);
     return APR_SUCCESS;
 }
 
-/* Create a dummy wakeup pipe for interrupting the poller
- */
-static apr_status_t create_wakeup_pipe(apr_pollset_t *pollset)
+static apr_status_t impl_pollset_create(apr_pollset_t *pollset,
+                                        apr_uint32_t size,
+                                        apr_pool_t *p,
+                                        apr_uint32_t flags)
 {
     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];
-    /* Add the pipe to the pollset
-     */
-    return apr_pollset_add(pollset, &fd);
-}
-
-/* Read and discard what's ever in the wakeup pipe.
- */
-static void 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;
-    }
-}
-
-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_status_t rv = APR_SUCCESS;
-    *pollset = apr_palloc(p, sizeof(**pollset));
+    pollset->p = apr_palloc(p, sizeof(apr_pollset_private_t));
 #if APR_HAS_THREADS
     if (flags & APR_POLLSET_THREADSAFE &&
-        ((rv = apr_thread_mutex_create(&(*pollset)->ring_lock,
+        ((rv = apr_thread_mutex_create(&pollset->p->ring_lock,
                                        APR_THREAD_MUTEX_DEFAULT,
                                        p)) != APR_SUCCESS)) {
-        *pollset = NULL;
+        pollset->p = NULL;
         return rv;
     }
 #else
     if (flags & APR_POLLSET_THREADSAFE) {
-        *pollset = NULL;
+        pollset->p = NULL;
         return APR_ENOTIMPL;
     }
 #endif
-    if (flags & APR_POLLSET_WAKEABLE) {
-        /* Add room for wakeup descriptor */
-        size++;
-    }
 
-    (*pollset)->nelts = 0;
-    (*pollset)->nalloc = size;
-    (*pollset)->flags = flags;
-    (*pollset)->pool = p;
+    /* POLLIN and POLLOUT are represented in different returned
+     * events, so we need 2 entries per descriptor in the result set,
+     * both for what is returned by kevent() and what is returned to
+     * the caller of apr_pollset_poll() (since it doesn't spend the
+     * CPU to coalesce separate APR_POLLIN and APR_POLLOUT events
+     * for the same descriptor)
+     */
+    pollset->p->setsize = 2 * size;
 
-    (*pollset)->ke_set =
-        (struct kevent *) apr_palloc(p, size * sizeof(struct kevent));
+    pollset->p->ke_set =
+        (struct kevent *) apr_palloc(p, pollset->p->setsize * sizeof(struct kevent));
 
-    memset((*pollset)->ke_set, 0, size * sizeof(struct kevent));
+    memset(pollset->p->ke_set, 0, pollset->p->setsize * sizeof(struct kevent));
 
-    (*pollset)->kqueue_fd = kqueue();
+    pollset->p->kqueue_fd = kqueue();
 
-    if ((*pollset)->kqueue_fd == -1) {
+    if (pollset->p->kqueue_fd == -1) {
+        pollset->p = NULL;
         return apr_get_netos_error();
     }
 
     {
         int flags;
 
-        if ((flags = fcntl((*pollset)->kqueue_fd, F_GETFD)) == -1)
+        if ((flags = fcntl(pollset->p->kqueue_fd, F_GETFD)) == -1)
             return errno;
 
         flags |= FD_CLOEXEC;
-        if (fcntl((*pollset)->kqueue_fd, F_SETFD, flags) == -1)
+        if (fcntl(pollset->p->kqueue_fd, F_SETFD, flags) == -1)
             return errno;
     }
 
-    (*pollset)->result_set = apr_palloc(p, size * sizeof(apr_pollfd_t));
+    pollset->p->result_set = apr_palloc(p, pollset->p->setsize * sizeof(apr_pollfd_t));
 
-    APR_RING_INIT(&(*pollset)->query_ring, pfd_elem_t, link);
-    APR_RING_INIT(&(*pollset)->free_ring, pfd_elem_t, link);
-    APR_RING_INIT(&(*pollset)->dead_ring, pfd_elem_t, link);
-    if (flags & APR_POLLSET_WAKEABLE) {
-        /* Create wakeup pipe */
-        if ((rv = create_wakeup_pipe(*pollset)) != APR_SUCCESS) {
-            close((*pollset)->kqueue_fd);
-            *pollset = NULL;
-            return rv;
-        }
-    }
-    apr_pool_cleanup_register(p, (void *) (*pollset), backend_cleanup,
-                              apr_pool_cleanup_null);
+    APR_RING_INIT(&pollset->p->query_ring, pfd_elem_t, link);
+    APR_RING_INIT(&pollset->p->free_ring, pfd_elem_t, link);
+    APR_RING_INIT(&pollset->p->dead_ring, pfd_elem_t, link);
 
-    return rv;
-}
-
-APR_DECLARE(apr_status_t) apr_pollset_destroy(apr_pollset_t * pollset)
-{
-    return apr_pool_cleanup_run(pollset->pool, pollset, backend_cleanup);
+    return APR_SUCCESS;
 }
 
-APR_DECLARE(apr_status_t) apr_pollset_add(apr_pollset_t *pollset,
-                                          const apr_pollfd_t *descriptor)
+static apr_status_t impl_pollset_add(apr_pollset_t *pollset,
+                                     const apr_pollfd_t *descriptor)
 {
     apr_os_sock_t fd;
     pfd_elem_t *elem;
@@ -201,8 +141,8 @@
 
     pollset_lock_rings();
 
-    if (!APR_RING_EMPTY(&(pollset->free_ring), pfd_elem_t, link)) {
-        elem = APR_RING_FIRST(&(pollset->free_ring));
+    if (!APR_RING_EMPTY(&(pollset->p->free_ring), pfd_elem_t, link)) {
+        elem = APR_RING_FIRST(&(pollset->p->free_ring));
         APR_RING_REMOVE(elem, link);
     }
     else {
@@ -219,29 +159,28 @@
     }
 
     if (descriptor->reqevents & APR_POLLIN) {
-        EV_SET(&pollset->kevent, fd, EVFILT_READ, EV_ADD, 0, 0, elem);
+        EV_SET(&pollset->p->kevent, fd, EVFILT_READ, EV_ADD, 0, 0, elem);
 
-        if (kevent(pollset->kqueue_fd, &pollset->kevent, 1, NULL, 0,
+        if (kevent(pollset->p->kqueue_fd, &pollset->p->kevent, 1, NULL, 0,
                    NULL) == -1) {
             rv = apr_get_netos_error();
         }
     }
 
     if (descriptor->reqevents & APR_POLLOUT && rv == APR_SUCCESS) {
-        EV_SET(&pollset->kevent, fd, EVFILT_WRITE, EV_ADD, 0, 0, elem);
+        EV_SET(&pollset->p->kevent, fd, EVFILT_WRITE, EV_ADD, 0, 0, elem);
 
-        if (kevent(pollset->kqueue_fd, &pollset->kevent, 1, NULL, 0,
+        if (kevent(pollset->p->kqueue_fd, &pollset->p->kevent, 1, NULL, 0,
                    NULL) == -1) {
             rv = apr_get_netos_error();
         }
     }
 
     if (rv == APR_SUCCESS) {
-        pollset->nelts++;
-        APR_RING_INSERT_TAIL(&(pollset->query_ring), elem, pfd_elem_t, link);
+        APR_RING_INSERT_TAIL(&(pollset->p->query_ring), elem, pfd_elem_t, link);
     }
     else {
-        APR_RING_INSERT_TAIL(&(pollset->free_ring), elem, pfd_elem_t, link);
+        APR_RING_INSERT_TAIL(&(pollset->p->free_ring), elem, pfd_elem_t, link);
     }
 
     pollset_unlock_rings();
@@ -249,11 +188,11 @@
     return rv;
 }
 
-APR_DECLARE(apr_status_t) apr_pollset_remove(apr_pollset_t *pollset,
-                                             const apr_pollfd_t *descriptor)
+static apr_status_t impl_pollset_remove(apr_pollset_t *pollset,
+                                        const apr_pollfd_t *descriptor)
 {
     pfd_elem_t *ep;
-    apr_status_t rv = APR_SUCCESS;
+    apr_status_t rv;
     apr_os_sock_t fd;
 
     pollset_lock_rings();
@@ -265,36 +204,35 @@
         fd = descriptor->desc.f->filedes;
     }
 
+    rv = APR_NOTFOUND; /* unless at least one of the specified conditions is */
     if (descriptor->reqevents & APR_POLLIN) {
-        EV_SET(&pollset->kevent, fd, EVFILT_READ, EV_DELETE, 0, 0, NULL);
+        EV_SET(&pollset->p->kevent, fd, EVFILT_READ, EV_DELETE, 0, 0, NULL);
 
-        if (kevent(pollset->kqueue_fd, &pollset->kevent, 1, NULL, 0,
-                   NULL) == -1) {
-            rv = APR_NOTFOUND;
+        if (kevent(pollset->p->kqueue_fd, &pollset->p->kevent, 1, NULL, 0,
+                   NULL) != -1) {
+            rv = APR_SUCCESS;
         }
     }
 
-    if (descriptor->reqevents & APR_POLLOUT && rv == APR_SUCCESS) {
-        EV_SET(&pollset->kevent, fd, EVFILT_WRITE, EV_DELETE, 0, 0, NULL);
+    if (descriptor->reqevents & APR_POLLOUT) {
+        EV_SET(&pollset->p->kevent, fd, EVFILT_WRITE, EV_DELETE, 0, 0, NULL);
 
-        if (kevent(pollset->kqueue_fd, &pollset->kevent, 1, NULL, 0,
-                   NULL) == -1) {
-            rv = APR_NOTFOUND;
+        if (kevent(pollset->p->kqueue_fd, &pollset->p->kevent, 1, NULL, 0,
+                   NULL) != -1) {
+            rv = APR_SUCCESS;
         }
     }
 
-    if (!APR_RING_EMPTY(&(pollset->query_ring), pfd_elem_t, link)) {
-        for (ep = APR_RING_FIRST(&(pollset->query_ring));
-             ep != APR_RING_SENTINEL(&(pollset->query_ring),
-                                     pfd_elem_t, link);
-             ep = APR_RING_NEXT(ep, link)) {
-
-            if (descriptor->desc.s == ep->pfd.desc.s) {
-                APR_RING_REMOVE(ep, link);
-                APR_RING_INSERT_TAIL(&(pollset->dead_ring),
-                                     ep, pfd_elem_t, link);
-                break;
-            }
+    for (ep = APR_RING_FIRST(&(pollset->p->query_ring));
+         ep != APR_RING_SENTINEL(&(pollset->p->query_ring),
+                                 pfd_elem_t, link);
+         ep = APR_RING_NEXT(ep, link)) {
+
+        if (descriptor->desc.s == ep->pfd.desc.s) {
+            APR_RING_REMOVE(ep, link);
+            APR_RING_INSERT_TAIL(&(pollset->p->dead_ring),
+                                 ep, pfd_elem_t, link);
+            break;
         }
     }
 
@@ -303,10 +241,10 @@
     return rv;
 }
 
-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)
+static apr_status_t impl_pollset_poll(apr_pollset_t *pollset,
+                                      apr_interval_time_t timeout,
+                                      apr_int32_t *num,
+                                      const apr_pollfd_t **descriptors)
 {
     int ret, i, j;
     struct timespec tv, *tvptr;
@@ -322,8 +260,8 @@
         tvptr = &tv;
     }
 
-    ret = kevent(pollset->kqueue_fd, NULL, 0, pollset->ke_set, pollset->nalloc,
-                tvptr);
+    ret = kevent(pollset->p->kqueue_fd, NULL, 0, pollset->p->ke_set,
+                 pollset->p->setsize, tvptr);
     (*num) = ret;
     if (ret < 0) {
         rv = apr_get_netos_error();
@@ -333,72 +271,68 @@
     }
     else {
         for (i = 0, j = 0; i < ret; i++) {
-            fd = (((pfd_elem_t*)(pollset->ke_set[i].udata))->pfd);
+            fd = (((pfd_elem_t*)(pollset->p->ke_set[i].udata))->pfd);
             if ((pollset->flags & APR_POLLSET_WAKEABLE) &&
                 fd.desc_type == APR_POLL_FILE &&
                 fd.desc.f == pollset->wakeup_pipe[0]) {
-                drain_wakeup_pipe(pollset);
+                apr_pollset_drain_wakeup_pipe(pollset);
                 rv = APR_EINTR;
             }
             else {
-                pollset->result_set[j] = fd;
-                pollset->result_set[j].rtnevents =
-                        get_kqueue_revent(pollset->ke_set[i].filter,
-                                          pollset->ke_set[i].flags);
+                pollset->p->result_set[j] = fd;
+                pollset->p->result_set[j].rtnevents =
+                        get_kqueue_revent(pollset->p->ke_set[i].filter,
+                                          pollset->p->ke_set[i].flags);
                 j++;
             }
         }
-        if ((*num = j))
+        if ((*num = j)) { /* any event besides wakeup pipe? */
             rv = APR_SUCCESS;
-        if (descriptors) {
-            *descriptors = pollset->result_set;
+            if (descriptors) {
+                *descriptors = pollset->p->result_set;
+            }
         }
     }
 
 
     pollset_lock_rings();
 
-    /* Shift all PFDs in the Dead Ring to be Free Ring */
-    APR_RING_CONCAT(&(pollset->free_ring), &(pollset->dead_ring), pfd_elem_t, link);
+    /* Shift all PFDs in the Dead Ring to the Free Ring */
+    APR_RING_CONCAT(&(pollset->p->free_ring), &(pollset->p->dead_ring),
+                    pfd_elem_t, link);
 
     pollset_unlock_rings();
 
     return rv;
 }
 
-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;
-}
-
-struct apr_pollcb_t {
-    apr_pool_t *pool;
-    apr_uint32_t nalloc;
-    struct kevent *pollset;
-    int kqfd;
+static apr_pollset_provider_t impl = {
+    impl_pollset_create,
+    impl_pollset_add,
+    impl_pollset_remove,
+    impl_pollset_poll,
+    impl_pollset_cleanup,
+    "kqueue"
 };
 
+apr_pollset_provider_t *apr_pollset_provider_kqueue = &impl;
+
 static apr_status_t cb_cleanup(void *b_)
 {
     apr_pollcb_t *pollcb = (apr_pollcb_t *) b_;
-    close(pollcb->kqfd);
+    close(pollcb->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)
+static apr_status_t impl_pollcb_create(apr_pollcb_t *pollcb,
+                                       apr_uint32_t size,
+                                       apr_pool_t *p,
+                                       apr_uint32_t flags)
 {
     int fd;
     
     fd = kqueue();
     if (fd < 0) {
-        *pollcb = NULL;
         return apr_get_netos_error();
     }
 
@@ -413,18 +347,15 @@
             return errno;
     }
  
-    *pollcb = apr_palloc(p, sizeof(**pollcb));
-    (*pollcb)->nalloc = size;
-    (*pollcb)->pool = p;
-    (*pollcb)->kqfd = fd;
-    (*pollcb)->pollset = (struct kevent *)apr_pcalloc(p, size * sizeof(struct kevent));
-    apr_pool_cleanup_register(p, *pollcb, cb_cleanup, cb_cleanup);
+    pollcb->fd = fd;
+    pollcb->pollset.ke = (struct kevent *)apr_pcalloc(p, 2 * size * sizeof(struct kevent));
+    apr_pool_cleanup_register(p, pollcb, cb_cleanup, apr_pool_cleanup_null);
     
     return APR_SUCCESS;
 }
 
-APR_DECLARE(apr_status_t) apr_pollcb_add(apr_pollcb_t *pollcb,
-                                         apr_pollfd_t *descriptor)
+static apr_status_t impl_pollcb_add(apr_pollcb_t *pollcb,
+                                    apr_pollfd_t *descriptor)
 {
     apr_os_sock_t fd;
     struct kevent ev;
@@ -440,7 +371,7 @@
     if (descriptor->reqevents & APR_POLLIN) {
         EV_SET(&ev, fd, EVFILT_READ, EV_ADD, 0, 0, descriptor);
         
-        if (kevent(pollcb->kqfd, &ev, 1, NULL, 0, NULL) == -1) {
+        if (kevent(pollcb->fd, &ev, 1, NULL, 0, NULL) == -1) {
             rv = apr_get_netos_error();
         }
     }
@@ -448,7 +379,7 @@
     if (descriptor->reqevents & APR_POLLOUT && rv == APR_SUCCESS) {
         EV_SET(&ev, fd, EVFILT_WRITE, EV_ADD, 0, 0, descriptor);
         
-        if (kevent(pollcb->kqfd, &ev, 1, NULL, 0, NULL) == -1) {
+        if (kevent(pollcb->fd, &ev, 1, NULL, 0, NULL) == -1) {
             rv = apr_get_netos_error();
         }
     }
@@ -456,10 +387,10 @@
     return rv;
 }
 
-APR_DECLARE(apr_status_t) apr_pollcb_remove(apr_pollcb_t *pollcb,
-                                            apr_pollfd_t *descriptor)
+static apr_status_t impl_pollcb_remove(apr_pollcb_t *pollcb,
+                                       apr_pollfd_t *descriptor)
 {
-    apr_status_t rv = APR_SUCCESS;
+    apr_status_t rv;
     struct kevent ev;
     apr_os_sock_t fd;
     
@@ -469,23 +400,21 @@
     else {
         fd = descriptor->desc.f->filedes;
     }
-    
+
+    rv = APR_NOTFOUND; /* unless at least one of the specified conditions is */
     if (descriptor->reqevents & APR_POLLIN) {
         EV_SET(&ev, fd, EVFILT_READ, EV_DELETE, 0, 0, NULL);
         
-        if (kevent(pollcb->kqfd, &ev, 1, NULL, 0, NULL) == -1) {
-            rv = APR_NOTFOUND;
+        if (kevent(pollcb->fd, &ev, 1, NULL, 0, NULL) != -1) {
+            rv = APR_SUCCESS;
         }
     }
     
-    if (descriptor->reqevents & APR_POLLOUT && rv == APR_SUCCESS) {
-        /* XXXX: this is less than optimal, shouldn't we still try to 
-         *        remove the FD even if it wasn't in the readset?
-         */
+    if (descriptor->reqevents & APR_POLLOUT) {
         EV_SET(&ev, fd, EVFILT_WRITE, EV_DELETE, 0, 0, NULL);
         
-        if (kevent(pollcb->kqfd, &ev, 1, NULL, 0, NULL) == -1) {
-            rv = APR_NOTFOUND;
+        if (kevent(pollcb->fd, &ev, 1, NULL, 0, NULL) != -1) {
+            rv = APR_SUCCESS;
         }
     }
     
@@ -493,10 +422,10 @@
 }
 
 
-APR_DECLARE(apr_status_t) apr_pollcb_poll(apr_pollcb_t *pollcb,
-                                          apr_interval_time_t timeout,
-                                          apr_pollcb_cb_t func,
-                                          void *baton)
+static apr_status_t impl_pollcb_poll(apr_pollcb_t *pollcb,
+                                     apr_interval_time_t timeout,
+                                     apr_pollcb_cb_t func,
+                                     void *baton)
 {
     int ret, i;
     struct timespec tv, *tvptr;
@@ -511,7 +440,7 @@
         tvptr = &tv;
     }
     
-    ret = kevent(pollcb->kqfd, NULL, 0, pollcb->pollset, pollcb->nalloc,
+    ret = kevent(pollcb->fd, NULL, 0, pollcb->pollset.ke, 2 * pollcb->nalloc,
                  tvptr);
 
     if (ret < 0) {
@@ -522,10 +451,10 @@
     }
     else {
         for (i = 0; i < ret; i++) {
-            apr_pollfd_t *pollfd = (apr_pollfd_t *)(pollcb->pollset[i].udata);
+            apr_pollfd_t *pollfd = (apr_pollfd_t *)(pollcb->pollset.ke[i].udata);
             
-            pollfd->rtnevents = get_kqueue_revent(pollcb->pollset[i].filter,
-                                                  pollcb->pollset[i].flags);
+            pollfd->rtnevents = get_kqueue_revent(pollcb->pollset.ke[i].filter,
+                                                  pollcb->pollset.ke[i].flags);
             
             rv = func(baton, pollfd);
             
@@ -538,4 +467,14 @@
     return rv;
 }
 
-#endif /* POLLSET_USES_KQUEUE */
+static apr_pollcb_provider_t impl_cb = {
+    impl_pollcb_create,
+    impl_pollcb_add,
+    impl_pollcb_remove,
+    impl_pollcb_poll,
+    "kqueue"
+};
+
+apr_pollcb_provider_t *apr_pollcb_provider_kqueue = &impl_cb;
+
+#endif /* HAVE_KQUEUE */

Modified: apr/apr/branches/1.4.x/poll/unix/poll.c
URL: http://svn.apache.org/viewvc/apr/apr/branches/1.4.x/poll/unix/poll.c?rev=821199&r1=821198&r2=821199&view=diff
==============================================================================
--- apr/apr/branches/1.4.x/poll/unix/poll.c (original)
+++ apr/apr/branches/1.4.x/poll/unix/poll.c Fri Oct  2 23:24:56 2009
@@ -14,9 +14,16 @@
  * limitations under the License.
  */
 
+#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_misc.h"
 #include "apr_arch_poll_private.h"
 
-#if defined(POLL_USES_POLL) || defined(POLLSET_USES_POLL)
+#if defined(HAVE_POLL)
 
 #ifdef HAVE_ALLOCA_H
 #include <alloca.h>
@@ -32,12 +39,7 @@
         rv |= POLLPRI;
     if (event & APR_POLLOUT)
         rv |= POLLOUT;
-    if (event & APR_POLLERR)
-        rv |= POLLERR;
-    if (event & APR_POLLHUP)
-        rv |= POLLHUP;
-    if (event & APR_POLLNVAL)
-        rv |= POLLNVAL;
+    /* POLLERR, POLLHUP, and POLLNVAL aren't valid as requested events */
 
     return rv;
 }
@@ -62,9 +64,6 @@
     return rv;
 }
 
-#endif /* POLL_USES_POLL || POLLSET_USES_POLL */
-
-
 #ifdef POLL_USES_POLL
 
 #define SMALL_POLLSET_LIMIT  8
@@ -148,163 +147,82 @@
 
 #endif /* POLL_USES_POLL */
 
-
-#ifdef POLLSET_USES_POLL
-
-struct apr_pollset_t
+struct apr_pollset_private_t
 {
-    apr_pool_t *pool;
-    apr_uint32_t nelts;
-    apr_uint32_t nalloc;
-    apr_uint32_t flags;
-    /* Pipe descriptors used for wakeup */
-    apr_file_t *wakeup_pipe[2];    
     struct pollfd *pollset;
     apr_pollfd_t *query_set;
     apr_pollfd_t *result_set;
 };
 
-/* 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];
-    /* Add the pipe to the pollset
-     */
-    return apr_pollset_add(pollset, &fd);
-}
-
-/* Read and discard what's ever in the wakeup pipe.
- */
-static void 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 wakeup_pipe_cleanup(void *p)
-{
-    apr_pollset_t *pollset = (apr_pollset_t *) p;
-    if (pollset->flags & APR_POLLSET_WAKEABLE) {
-        /* Close both sides of the wakeup pipe */
-        if (pollset->wakeup_pipe[0]) {
-            apr_file_close(pollset->wakeup_pipe[0]);
-            pollset->wakeup_pipe[0] = NULL;
-        }
-        if (pollset->wakeup_pipe[1]) {
-            apr_file_close(pollset->wakeup_pipe[1]);
-            pollset->wakeup_pipe[1] = NULL;
-        }
-    }
-
-    return APR_SUCCESS;
-}
-
-APR_DECLARE(apr_status_t) apr_pollset_create(apr_pollset_t **pollset,
-                                             apr_uint32_t size,
-                                             apr_pool_t *p,
-                                             apr_uint32_t flags)
+static apr_status_t impl_pollset_create(apr_pollset_t *pollset,
+                                        apr_uint32_t size,
+                                        apr_pool_t *p,
+                                        apr_uint32_t flags)
 {
     if (flags & APR_POLLSET_THREADSAFE) {                
-        *pollset = NULL;
         return APR_ENOTIMPL;
     }
-    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)->pollset = apr_palloc(p, size * sizeof(struct pollfd));
-    (*pollset)->query_set = apr_palloc(p, size * sizeof(apr_pollfd_t));
-    (*pollset)->result_set = apr_palloc(p, size * sizeof(apr_pollfd_t));
-
-    if (flags & APR_POLLSET_WAKEABLE) {
-        apr_status_t rv;
-        /* Create wakeup pipe */
-        if ((rv = create_wakeup_pipe(*pollset)) != APR_SUCCESS) {
-            *pollset = NULL;
-            return rv;
-        }
-        apr_pool_cleanup_register(p, *pollset, wakeup_pipe_cleanup,
-                                  apr_pool_cleanup_null);
+#ifdef WIN32
+    if (!APR_HAVE_LATE_DLL_FUNC(WSAPoll)) {
+        return APR_ENOTIMPL;
     }
-    return APR_SUCCESS;
-}
+#endif
+    pollset->p = apr_palloc(p, sizeof(apr_pollset_private_t));
+    pollset->p->pollset = apr_palloc(p, size * sizeof(struct pollfd));
+    pollset->p->query_set = apr_palloc(p, size * sizeof(apr_pollfd_t));
+    pollset->p->result_set = apr_palloc(p, size * sizeof(apr_pollfd_t));
 
-APR_DECLARE(apr_status_t) apr_pollset_destroy(apr_pollset_t *pollset)
-{
-    if (pollset->flags & APR_POLLSET_WAKEABLE) 
-        return apr_pool_cleanup_run(pollset->pool, pollset,
-                                    wakeup_pipe_cleanup);
-    else
-        return APR_SUCCESS;
+    return APR_SUCCESS;
 }
 
-APR_DECLARE(apr_status_t) apr_pollset_add(apr_pollset_t *pollset,
-                                          const apr_pollfd_t *descriptor)
+static apr_status_t impl_pollset_add(apr_pollset_t *pollset,
+                                     const apr_pollfd_t *descriptor)
 {
     if (pollset->nelts == pollset->nalloc) {
         return APR_ENOMEM;
     }
 
-    pollset->query_set[pollset->nelts] = *descriptor;
+    pollset->p->query_set[pollset->nelts] = *descriptor;
 
     if (descriptor->desc_type == APR_POLL_SOCKET) {
-        pollset->pollset[pollset->nelts].fd = descriptor->desc.s->socketdes;
+        pollset->p->pollset[pollset->nelts].fd = descriptor->desc.s->socketdes;
     }
     else {
-        pollset->pollset[pollset->nelts].fd = descriptor->desc.f->filedes;
+#if APR_FILES_AS_SOCKETS
+        pollset->p->pollset[pollset->nelts].fd = descriptor->desc.f->filedes;
+#else
+        if ((pollset->flags & APR_POLLSET_WAKEABLE) &&
+            descriptor->desc.f == pollset->wakeup_pipe[0])
+            pollset->p->pollset[pollset->nelts].fd = (SOCKET)descriptor->desc.f->filedes;
+        else
+            return APR_EBADF;
+#endif
     }
-
-    pollset->pollset[pollset->nelts].events =
+    pollset->p->pollset[pollset->nelts].events =
         get_event(descriptor->reqevents);
     pollset->nelts++;
 
     return APR_SUCCESS;
 }
 
-APR_DECLARE(apr_status_t) apr_pollset_remove(apr_pollset_t *pollset,
-                                             const apr_pollfd_t *descriptor)
+static apr_status_t impl_pollset_remove(apr_pollset_t *pollset,
+                                        const apr_pollfd_t *descriptor)
 {
     apr_uint32_t i;
 
     for (i = 0; i < pollset->nelts; i++) {
-        if (descriptor->desc.s == pollset->query_set[i].desc.s) {
+        if (descriptor->desc.s == pollset->p->query_set[i].desc.s) {
             /* Found an instance of the fd: remove this and any other copies */
             apr_uint32_t dst = i;
             apr_uint32_t old_nelts = pollset->nelts;
             pollset->nelts--;
             for (i++; i < old_nelts; i++) {
-                if (descriptor->desc.s == pollset->query_set[i].desc.s) {
+                if (descriptor->desc.s == pollset->p->query_set[i].desc.s) {
                     pollset->nelts--;
                 }
                 else {
-                    pollset->pollset[dst] = pollset->pollset[i];
-                    pollset->query_set[dst] = pollset->query_set[i];
+                    pollset->p->pollset[dst] = pollset->p->pollset[i];
+                    pollset->p->query_set[dst] = pollset->p->query_set[i];
                     dst++;
                 }
             }
@@ -315,10 +233,10 @@
     return APR_NOTFOUND;
 }
 
-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)
+static apr_status_t impl_pollset_poll(apr_pollset_t *pollset,
+                                      apr_interval_time_t timeout,
+                                      apr_int32_t *num,
+                                      const apr_pollfd_t **descriptors)
 {
     int ret;
     apr_status_t rv = APR_SUCCESS;
@@ -327,7 +245,11 @@
     if (timeout > 0) {
         timeout /= 1000;
     }
-    ret = poll(pollset->pollset, pollset->nelts, timeout);
+#ifdef WIN32
+    ret = WSAPoll(pollset->p->pollset, pollset->nelts, (int)timeout);
+#else
+    ret = poll(pollset->p->pollset, pollset->nelts, timeout);
+#endif
     (*num) = ret;
     if (ret < 0) {
         return apr_get_netos_error();
@@ -337,68 +259,168 @@
     }
     else {
         for (i = 0, j = 0; i < pollset->nelts; i++) {
-            if (pollset->pollset[i].revents != 0) {
+            if (pollset->p->pollset[i].revents != 0) {
                 /* Check if the polled descriptor is our
                  * wakeup pipe. In that case do not put it result set.
                  */
                 if ((pollset->flags & APR_POLLSET_WAKEABLE) &&
-                    pollset->query_set[i].desc_type == APR_POLL_FILE &&
-                    pollset->query_set[i].desc.f == pollset->wakeup_pipe[0]) {
-                        drain_wakeup_pipe(pollset);
+                    pollset->p->query_set[i].desc_type == APR_POLL_FILE &&
+                    pollset->p->query_set[i].desc.f == pollset->wakeup_pipe[0]) {
+                        apr_pollset_drain_wakeup_pipe(pollset);
                         rv = APR_EINTR;
                 }
                 else {
-                    pollset->result_set[j] = pollset->query_set[i];
-                    pollset->result_set[j].rtnevents =
-                        get_revent(pollset->pollset[i].revents);
+                    pollset->p->result_set[j] = pollset->p->query_set[i];
+                    pollset->p->result_set[j].rtnevents =
+                        get_revent(pollset->p->pollset[i].revents);
                     j++;
                 }
             }
         }
-        if (((*num) = j)) {
+        if (((*num) = j) > 0)
             rv = APR_SUCCESS;
-        }
     }
     if (descriptors && (*num))
-        *descriptors = pollset->result_set;
+        *descriptors = pollset->p->result_set;
     return rv;
 }
 
-APR_DECLARE(apr_status_t) apr_pollset_wakeup(apr_pollset_t *pollset)
+static apr_pollset_provider_t impl = {
+    impl_pollset_create,
+    impl_pollset_add,
+    impl_pollset_remove,
+    impl_pollset_poll,
+    NULL,
+    "poll"
+};
+
+apr_pollset_provider_t *apr_pollset_provider_poll = &impl;
+
+/* Poll method pollcb.
+ * This is probably usable only for WIN32 having WSAPoll
+ */
+static apr_status_t impl_pollcb_create(apr_pollcb_t *pollcb,
+                                       apr_uint32_t size,
+                                       apr_pool_t *p,
+                                       apr_uint32_t flags)
 {
-    if (pollset->flags & APR_POLLSET_WAKEABLE)
-        return apr_file_putc(1, pollset->wakeup_pipe[1]);
-    else
-        return APR_EINIT;
+#if APR_HAS_THREADS
+  return APR_ENOTIMPL;
+#endif
+
+    pollcb->fd = -1;
+#ifdef WIN32
+    if (!APR_HAVE_LATE_DLL_FUNC(WSAPoll)) {
+        return APR_ENOTIMPL;
+    }
+#endif
+
+    pollcb->pollset.ps = apr_palloc(p, size * sizeof(struct pollfd));
+    pollcb->copyset = apr_palloc(p, size * sizeof(apr_pollfd_t *));
+
+    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)
+static apr_status_t impl_pollcb_add(apr_pollcb_t *pollcb,
+                                    apr_pollfd_t *descriptor)
 {
-    return APR_ENOTIMPL;
+    if (pollcb->nelts == pollcb->nalloc) {
+        return APR_ENOMEM;
+    }
+
+    if (descriptor->desc_type == APR_POLL_SOCKET) {
+        pollcb->pollset.ps[pollcb->nelts].fd = descriptor->desc.s->socketdes;
+    }
+    else {
+#if APR_FILES_AS_SOCKETS
+        pollcb->pollset.ps[pollcb->nelts].fd = descriptor->desc.f->filedes;
+#else
+        return APR_EBADF;
+#endif
+    }
+
+    pollcb->pollset.ps[pollcb->nelts].events =
+        get_event(descriptor->reqevents);
+    pollcb->copyset[pollcb->nelts] = descriptor;
+    pollcb->nelts++;
+    
+    return APR_SUCCESS;
 }
 
-APR_DECLARE(apr_status_t) apr_pollcb_add(apr_pollcb_t *pollcb,
-                                         apr_pollfd_t *descriptor)
+static apr_status_t impl_pollcb_remove(apr_pollcb_t *pollcb,
+                                       apr_pollfd_t *descriptor)
 {
-    return APR_ENOTIMPL;
+    apr_uint32_t i;
+
+    for (i = 0; i < pollcb->nelts; i++) {
+        if (descriptor->desc.s == pollcb->copyset[i]->desc.s) {
+            /* Found an instance of the fd: remove this and any other copies */
+            apr_uint32_t dst = i;
+            apr_uint32_t old_nelts = pollcb->nelts;
+            pollcb->nelts--;
+            for (i++; i < old_nelts; i++) {
+                if (descriptor->desc.s == pollcb->copyset[i]->desc.s) {
+                    pollcb->nelts--;
+                }
+                else {
+                    pollcb->pollset.ps[dst] = pollcb->pollset.ps[i];
+                    pollcb->copyset[dst] = pollcb->copyset[i];
+                    dst++;
+                }
+            }
+            return APR_SUCCESS;
+        }
+    }
+
+    return APR_NOTFOUND;
 }
 
-APR_DECLARE(apr_status_t) apr_pollcb_remove(apr_pollcb_t *pollcb,
-                                            apr_pollfd_t *descriptor)
+static apr_status_t impl_pollcb_poll(apr_pollcb_t *pollcb,
+                                     apr_interval_time_t timeout,
+                                     apr_pollcb_cb_t func,
+                                     void *baton)
 {
-    return APR_ENOTIMPL;
+    int ret;
+    apr_status_t rv = APR_SUCCESS;
+    apr_uint32_t i;
+
+    if (timeout > 0) {
+        timeout /= 1000;
+    }
+#ifdef WIN32
+    ret = WSAPoll(pollcb->pollset.ps, pollcb->nelts, (int)timeout);
+#else
+    ret = poll(pollcb->pollset.ps, pollcb->nelts, timeout);
+#endif
+    if (ret < 0) {
+        return apr_get_netos_error();
+    }
+    else if (ret == 0) {
+        return APR_TIMEUP;
+    }
+    else {
+        for (i = 0; i < pollcb->nelts; i++) {
+            if (pollcb->pollset.ps[i].revents != 0) {
+                apr_pollfd_t *pollfd = pollcb->copyset[i];
+                pollfd->rtnevents = get_revent(pollcb->pollset.ps[i].revents);                    
+                rv = func(baton, pollfd);
+                if (rv) {
+                    return rv;
+                }
+            }
+        }
+    }
+    return rv;
 }
 
+static apr_pollcb_provider_t impl_cb = {
+    impl_pollcb_create,
+    impl_pollcb_add,
+    impl_pollcb_remove,
+    impl_pollcb_poll,
+    "poll"
+};
 
-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 APR_ENOTIMPL;
-}
+apr_pollcb_provider_t *apr_pollcb_provider_poll = &impl_cb;
 
-#endif /* POLLSET_USES_POLL */
+#endif /* HAVE_POLL */