Loading...
Searching...
No Matches
as_poll.h
Go to the documentation of this file.
1/*
2 * Copyright 2008-2018 Aerospike, Inc.
3 *
4 * Portions may be licensed to Aerospike, Inc. under one or more contributor
5 * license agreements.
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
8 * use this file except in compliance with the License. You may obtain a copy of
9 * the License at http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14 * License for the specific language governing permissions and limitations under
15 * the License.
16 */
17#pragma once
18
19#if !defined(_MSC_VER)
20#include <sys/select.h>
21#endif
22
23#ifdef __cplusplus
24extern "C" {
25#endif
26
27/******************************************************************************
28 * TYPES
29 *****************************************************************************/
30
31typedef struct as_poll_s {
32#if !defined(_MSC_VER)
33 size_t size;
34 fd_set* set;
35#else
36 fd_set set;
37#endif
38} as_poll;
39
40/******************************************************************************
41 * INLINE FUNCTIONS
42 *****************************************************************************/
43
44#if !defined(_MSC_VER)
45
46#define AS_STACK_LIMIT (16 * 1024)
47
48// There is a conflict even among various versions of linux,
49// because it's common to compile kernels - or set ulimits -
50// where the FD_SETSIZE is much greater than a compiled version.
51// Thus, we can compute the required size of the fdset and use a reasonable size
52// the other option is using epoll, which is a little scary for this kind of
53// "I just want a timeout" usage.
54//
55// The reality is 8 bits per byte, but this calculation is a little more general.
56// Roundup fd in increments of FD_SETSIZE and convert to bytes.
57#define as_poll_init(_poll, _fd)\
58 (_poll)->size = (((_fd) / FD_SETSIZE) + 1) * FD_SETSIZE / 8;\
59 (_poll)->set = ((_poll)->size > AS_STACK_LIMIT)? cf_malloc((_poll)->size) : alloca((_poll)->size);
60
61static inline int
62as_poll_socket(as_poll* poll, as_socket_fd fd, uint32_t timeout, bool read)
63{
64 // From glibc-2.15 (ubuntu 12.0.4+), the FD_* functions has a check on the
65 // number of fds passed. According to the man page of FD_SET, the behavior
66 // is undefined for fd > 1024. But this is enforced from glibc-2.15
67 // https://sourceware.org/bugzilla/show_bug.cgi?id=10352
68 //
69 // So, manipulate the base and the offset of the fd in it.
70 memset(poll->set, 0, poll->size);
71 FD_SET(fd % FD_SETSIZE, &poll->set[fd / FD_SETSIZE]);
72
73 struct timeval tv;
74 struct timeval* tvp;
75 int rv;
76
77 if (timeout > 0) {
78 tv.tv_sec = timeout / 1000;
79 tv.tv_usec = (timeout % 1000) * 1000;
80 tvp = &tv;
81 }
82 else {
83 tvp = NULL;
84 }
85
86 if (read) {
87 rv = select(fd + 1, poll->set /*readfd*/, 0 /*writefd*/, 0/*oobfd*/, tvp);
88 }
89 else {
90 rv = select(fd + 1, 0 /*readfd*/, poll->set /*writefd*/, 0/*oobfd*/, tvp);
91 }
92
93 if (rv <= 0) {
94 return rv;
95 }
96
97 if (! FD_ISSET(fd % FD_SETSIZE, &poll->set[fd / FD_SETSIZE])) {
98 return -2;
99 }
100 return rv;
101}
102
103static inline void
105{
106 if (poll->size > AS_STACK_LIMIT) {
107 cf_free(poll->set);
108 }
109}
110
111#else // _MSC_VER
112
113#define as_poll_init(_poll, _fd)
114
115static inline int
116as_poll_socket(as_poll* poll, as_socket_fd fd, uint32_t timeout, bool read)
117{
118 FD_ZERO(&poll->set);
119 FD_SET(fd, &poll->set);
120
121 struct timeval tv;
122 struct timeval* tvp;
123 int rv;
124
125 if (timeout > 0) {
126 tv.tv_sec = timeout / 1000;
127 tv.tv_usec = (timeout % 1000) * 1000;
128 tvp = &tv;
129 }
130 else {
131 tvp = NULL;
132 }
133
134 if (read) {
135 rv = select(0, &poll->set /*readfd*/, 0 /*writefd*/, 0/*oobfd*/, tvp);
136 }
137 else {
138 rv = select(0, 0 /*readfd*/, &poll->set /*writefd*/, 0/*oobfd*/, tvp);
139 }
140
141 if (rv <= 0) {
142 return rv;
143 }
144
145 if (! FD_ISSET(fd, &poll->set)) {
146 return -2;
147 }
148 return rv;
149}
150
151#define as_poll_destroy(_poll)
152
153#endif
154
155#ifdef __cplusplus
156} // end extern "C"
157#endif
static int as_poll_socket(as_poll *poll, as_socket_fd fd, uint32_t timeout, bool read)
Definition as_poll.h:62
static void as_poll_destroy(as_poll *poll)
Definition as_poll.h:104
#define AS_STACK_LIMIT
Definition as_poll.h:46
#define as_socket_fd
Definition as_socket.h:32
fd_set * set
Definition as_poll.h:34
size_t size
Definition as_poll.h:33