All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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
24 extern "C" {
25 #endif
26 
27 /******************************************************************************
28  * TYPES
29  *****************************************************************************/
30 
31 typedef 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 
61 static inline int
62 as_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 
103 static 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 
115 static inline int
116 as_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 void as_poll_destroy(as_poll *poll)
Definition: as_poll.h:104
#define as_socket_fd
Definition: as_socket.h:32
fd_set * set
Definition: as_poll.h:34
#define AS_STACK_LIMIT
Definition: as_poll.h:46
static int as_poll_socket(as_poll *poll, as_socket_fd fd, uint32_t timeout, bool read)
Definition: as_poll.h:62
size_t size
Definition: as_poll.h:33