summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorjim <jim@13f79535-47bb-0310-9956-ffa450edef68>2009-10-02 23:24:56 +0000
committerjim <jim@13f79535-47bb-0310-9956-ffa450edef68>2009-10-02 23:24:56 +0000
commit5cad0beb419ccfc4deea258240d7b8a352fd4900 (patch)
treeb6f28948a0cec011515d402f54e81413eccd238b /include
parent4c2fd4bc0dae60c55184ad380291ad9d6eb4fe46 (diff)
downloadlibapr-5cad0beb419ccfc4deea258240d7b8a352fd4900.tar.gz
Backport all poll changes from r734707 up to now
from trunk. git-svn-id: http://svn.apache.org/repos/asf/apr/apr/branches/1.4.x@821199 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'include')
-rw-r--r--include/apr_poll.h184
-rw-r--r--include/arch/unix/apr_arch_poll_private.h86
2 files changed, 228 insertions, 42 deletions
diff --git a/include/apr_poll.h b/include/apr_poll.h
index 3e5d8f96d..9521eee92 100644
--- a/include/apr_poll.h
+++ b/include/apr_poll.h
@@ -49,14 +49,36 @@ extern "C" {
#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 @@ struct apr_pollfd_t {
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_DECLARE(apr_status_t) apr_pollset_create(apr_pollset_t **pollset,
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 @@ APR_DECLARE(apr_status_t) apr_pollset_destroy(apr_pollset_t *pollset);
* 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 @@ APR_DECLARE(apr_status_t) apr_pollset_add(apr_pollset_t *pollset,
* 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 @@ APR_DECLARE(apr_status_t) apr_pollset_remove(apr_pollset_t *pollset,
/**
* 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 @@ APR_DECLARE(apr_status_t) apr_pollset_poll(apr_pollset_t *pollset,
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 @@ APR_DECLARE(apr_status_t) apr_pollset_wakeup(apr_pollset_t *pollset);
* @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_DECLARE(apr_status_t) apr_poll(apr_pollfd_t *aprset, apr_int32_t numsock,
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_DECLARE(apr_status_t) apr_pollcb_create(apr_pollcb_t **pollcb,
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 @@ APR_DECLARE(apr_status_t) apr_pollcb_add(apr_pollcb_t *pollcb,
* 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 @@ typedef apr_status_t (*apr_pollcb_cb_t)(void *baton, apr_pollfd_t *descriptor);
/**
* 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,
diff --git a/include/arch/unix/apr_arch_poll_private.h b/include/arch/unix/apr_arch_poll_private.h
index f176eac0e..a26730490 100644
--- a/include/arch/unix/apr_arch_poll_private.h
+++ b/include/arch/unix/apr_arch_poll_private.h
@@ -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 @@ typedef struct pfd_elem_t pfd_elem_t;
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 */