pollcb.c revision 269847
1/* Licensed to the Apache Software Foundation (ASF) under one or more 2 * contributor license agreements. See the NOTICE file distributed with 3 * this work for additional information regarding copyright ownership. 4 * The ASF licenses this file to You under the Apache License, Version 2.0 5 * (the "License"); you may not use this file except in compliance with 6 * the License. You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#ifdef WIN32 18/* POSIX defines 1024 for the FD_SETSIZE */ 19#define FD_SETSIZE 1024 20#endif 21 22#include "apr.h" 23#include "apr_poll.h" 24#include "apr_time.h" 25#include "apr_portable.h" 26#include "apr_arch_file_io.h" 27#include "apr_arch_networkio.h" 28#include "apr_arch_poll_private.h" 29 30static apr_pollset_method_e pollset_default_method = POLLSET_DEFAULT_METHOD; 31#if defined(HAVE_KQUEUE) 32extern apr_pollcb_provider_t *apr_pollcb_provider_kqueue; 33#endif 34#if defined(HAVE_PORT_CREATE) 35extern apr_pollcb_provider_t *apr_pollcb_provider_port; 36#endif 37#if defined(HAVE_EPOLL) 38extern apr_pollcb_provider_t *apr_pollcb_provider_epoll; 39#endif 40#if defined(HAVE_POLL) 41extern apr_pollcb_provider_t *apr_pollcb_provider_poll; 42#endif 43 44static apr_pollcb_provider_t *pollcb_provider(apr_pollset_method_e method) 45{ 46 apr_pollcb_provider_t *provider = NULL; 47 switch (method) { 48 case APR_POLLSET_KQUEUE: 49#if defined(HAVE_KQUEUE) 50 provider = apr_pollcb_provider_kqueue; 51#endif 52 break; 53 case APR_POLLSET_PORT: 54#if defined(HAVE_PORT_CREATE) 55 provider = apr_pollcb_provider_port; 56#endif 57 break; 58 case APR_POLLSET_EPOLL: 59#if defined(HAVE_EPOLL) 60 provider = apr_pollcb_provider_epoll; 61#endif 62 break; 63 case APR_POLLSET_POLL: 64#if defined(HAVE_POLL) 65 provider = apr_pollcb_provider_poll; 66#endif 67 break; 68 case APR_POLLSET_SELECT: 69 case APR_POLLSET_AIO_MSGQ: 70 case APR_POLLSET_DEFAULT: 71 break; 72 } 73 return provider; 74} 75 76APR_DECLARE(apr_status_t) apr_pollcb_create_ex(apr_pollcb_t **ret_pollcb, 77 apr_uint32_t size, 78 apr_pool_t *p, 79 apr_uint32_t flags, 80 apr_pollset_method_e method) 81{ 82 apr_status_t rv; 83 apr_pollcb_t *pollcb; 84 apr_pollcb_provider_t *provider = NULL; 85 86 *ret_pollcb = NULL; 87 88 #ifdef WIN32 89 /* This will work only if ws2_32.dll has WSAPoll funtion. 90 * We could check the presence of the function here, 91 * but someone might implement other pollcb method in 92 * the future. 93 */ 94 if (method == APR_POLLSET_DEFAULT) { 95 method = APR_POLLSET_POLL; 96 } 97 #endif 98 99 if (method == APR_POLLSET_DEFAULT) 100 method = pollset_default_method; 101 while (provider == NULL) { 102 provider = pollcb_provider(method); 103 if (!provider) { 104 if ((flags & APR_POLLSET_NODEFAULT) == APR_POLLSET_NODEFAULT) 105 return APR_ENOTIMPL; 106 if (method == pollset_default_method) 107 return APR_ENOTIMPL; 108 method = pollset_default_method; 109 } 110 } 111 112 pollcb = apr_palloc(p, sizeof(*pollcb)); 113 pollcb->nelts = 0; 114 pollcb->nalloc = size; 115 pollcb->pool = p; 116 pollcb->provider = provider; 117 118 rv = (*provider->create)(pollcb, size, p, flags); 119 if (rv == APR_ENOTIMPL) { 120 if (method == pollset_default_method) { 121 return rv; 122 } 123 124 if ((flags & APR_POLLSET_NODEFAULT) == APR_POLLSET_NODEFAULT) { 125 return rv; 126 } 127 128 /* Try with default provider */ 129 provider = pollcb_provider(pollset_default_method); 130 if (!provider) { 131 return APR_ENOTIMPL; 132 } 133 rv = (*provider->create)(pollcb, size, p, flags); 134 if (rv != APR_SUCCESS) { 135 return rv; 136 } 137 pollcb->provider = provider; 138 } 139 140 *ret_pollcb = pollcb; 141 return APR_SUCCESS; 142} 143 144APR_DECLARE(apr_status_t) apr_pollcb_create(apr_pollcb_t **pollcb, 145 apr_uint32_t size, 146 apr_pool_t *p, 147 apr_uint32_t flags) 148{ 149 apr_pollset_method_e method = APR_POLLSET_DEFAULT; 150 return apr_pollcb_create_ex(pollcb, size, p, flags, method); 151} 152 153APR_DECLARE(apr_status_t) apr_pollcb_add(apr_pollcb_t *pollcb, 154 apr_pollfd_t *descriptor) 155{ 156 return (*pollcb->provider->add)(pollcb, descriptor); 157} 158 159APR_DECLARE(apr_status_t) apr_pollcb_remove(apr_pollcb_t *pollcb, 160 apr_pollfd_t *descriptor) 161{ 162 return (*pollcb->provider->remove)(pollcb, descriptor); 163} 164 165 166APR_DECLARE(apr_status_t) apr_pollcb_poll(apr_pollcb_t *pollcb, 167 apr_interval_time_t timeout, 168 apr_pollcb_cb_t func, 169 void *baton) 170{ 171 return (*pollcb->provider->poll)(pollcb, timeout, func, baton); 172} 173