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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include "apr_arch_networkio.h"
23 struct apr_pollset_t {
32 apr_pollfd_t *query_set;
33 apr_pollfd_t *result_set;
38 APR_DECLARE(apr_status_t) apr_pollset_create(apr_pollset_t **pollset,
43 *pollset = apr_palloc(p, sizeof(**pollset));
45 (*pollset)->nelts = 0;
46 (*pollset)->nalloc = size;
47 (*pollset)->pollset = apr_palloc(p, size * sizeof(int) * 3);
48 (*pollset)->query_set = apr_palloc(p, size * sizeof(apr_pollfd_t));
49 (*pollset)->result_set = apr_palloc(p, size * sizeof(apr_pollfd_t));
50 (*pollset)->num_read = -1;
56 APR_DECLARE(apr_status_t) apr_pollset_destroy(apr_pollset_t *pollset)
58 /* A no-op function for now. If we later implement /dev/poll
59 * support, we'll need to close the /dev/poll fd here
66 APR_DECLARE(apr_status_t) apr_pollset_add(apr_pollset_t *pollset,
67 const apr_pollfd_t *descriptor)
69 if (pollset->nelts == pollset->nalloc) {
73 pollset->query_set[pollset->nelts] = *descriptor;
75 if (descriptor->desc_type != APR_POLL_SOCKET) {
80 pollset->num_read = -1;
86 APR_DECLARE(apr_status_t) apr_pollset_remove(apr_pollset_t *pollset,
87 const apr_pollfd_t *descriptor)
91 for (i = 0; i < pollset->nelts; i++) {
92 if (descriptor->desc.s == pollset->query_set[i].desc.s) {
93 /* Found an instance of the fd: remove this and any other copies */
95 apr_uint32_t old_nelts = pollset->nelts;
98 for (i++; i < old_nelts; i++) {
99 if (descriptor->desc.s == pollset->query_set[i].desc.s) {
103 pollset->pollset[dst] = pollset->pollset[i];
104 pollset->query_set[dst] = pollset->query_set[i];
109 pollset->num_read = -1;
119 static void make_pollset(apr_pollset_t *pollset)
124 pollset->num_read = 0;
125 pollset->num_write = 0;
126 pollset->num_except = 0;
128 for (i = 0; i < pollset->nelts; i++) {
129 if (pollset->query_set[i].reqevents & APR_POLLIN) {
130 pollset->pollset[pos++] = pollset->query_set[i].desc.s->socketdes;
135 for (i = 0; i < pollset->nelts; i++) {
136 if (pollset->query_set[i].reqevents & APR_POLLOUT) {
137 pollset->pollset[pos++] = pollset->query_set[i].desc.s->socketdes;
138 pollset->num_write++;
142 for (i = 0; i < pollset->nelts; i++) {
143 if (pollset->query_set[i].reqevents & APR_POLLPRI) {
144 pollset->pollset[pos++] = pollset->query_set[i].desc.s->socketdes;
145 pollset->num_except++;
149 pollset->num_total = pollset->num_read + pollset->num_write + pollset->num_except;
154 APR_DECLARE(apr_status_t) apr_pollset_poll(apr_pollset_t *pollset,
155 apr_interval_time_t timeout,
157 const apr_pollfd_t **descriptors)
162 int read_pos, write_pos, except_pos;
164 if (pollset->num_read < 0) {
165 make_pollset(pollset);
168 pollresult = alloca(sizeof(int) * pollset->num_total);
169 memcpy(pollresult, pollset->pollset, sizeof(int) * pollset->num_total);
176 rv = select(pollresult, pollset->num_read, pollset->num_write, pollset->num_except, timeout);
179 return APR_FROM_OS_ERROR(sock_errno());
187 write_pos = pollset->num_read;
188 except_pos = pollset->num_read + pollset->num_write;
190 for (i = 0; i < pollset->nelts; i++) {
193 if (pollset->query_set[i].reqevents & APR_POLLIN) {
194 if (pollresult[read_pos++] != -1) {
195 rtnevents |= APR_POLLIN;
199 if (pollset->query_set[i].reqevents & APR_POLLOUT) {
200 if (pollresult[write_pos++] != -1) {
201 rtnevents |= APR_POLLOUT;
205 if (pollset->query_set[i].reqevents & APR_POLLPRI) {
206 if (pollresult[except_pos++] != -1) {
207 rtnevents |= APR_POLLPRI;
212 pollset->result_set[*num] = pollset->query_set[i];
213 pollset->result_set[*num].rtnevents = rtnevents;
218 *descriptors = pollset->result_set;