diff options
author | jim <jim@13f79535-47bb-0310-9956-ffa450edef68> | 2009-10-02 23:24:56 +0000 |
---|---|---|
committer | jim <jim@13f79535-47bb-0310-9956-ffa450edef68> | 2009-10-02 23:24:56 +0000 |
commit | 5cad0beb419ccfc4deea258240d7b8a352fd4900 (patch) | |
tree | b6f28948a0cec011515d402f54e81413eccd238b /include | |
parent | 4c2fd4bc0dae60c55184ad380291ad9d6eb4fe46 (diff) | |
download | libapr-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.h | 184 | ||||
-rw-r--r-- | include/arch/unix/apr_arch_poll_private.h | 86 |
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 */ |