GNU libmicrohttpd  0.9.65
mhd_itc.h
Go to the documentation of this file.
1 /*
2  This file is part of libmicrohttpd
3  Copyright (C) 2016 Karlson2k (Evgeny Grin)
4 
5  This library is free software; you can redistribute it and/or
6  modify it under the terms of the GNU Lesser General Public
7  License as published by the Free Software Foundation; either
8  version 2.1 of the License, or (at your option) any later version.
9 
10  This library is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  Lesser General Public License for more details.
14 
15  You should have received a copy of the GNU Lesser General Public
16  License along with this library; if not, write to the Free Software
17  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 
19 */
20 
33 #ifndef MHD_ITC_H
34 #define MHD_ITC_H 1
35 #include "mhd_itc_types.h"
36 
37 #include <fcntl.h>
38 
39 #ifndef MHD_PANIC
40 # include <stdio.h>
41 # include <stdlib.h>
42 /* Simple implementation of MHD_PANIC, to be used outside lib */
43 # define MHD_PANIC(msg) do { fprintf (stderr, \
44  "Abnormal termination at %d line in file %s: %s\n", \
45  (int)__LINE__, __FILE__, msg); abort();} while(0)
46 #endif /* ! MHD_PANIC */
47 
48 #if defined(_MHD_ITC_EVENTFD)
49 
50 /* **************** Optimized GNU/Linux ITC implementation by eventfd ********** */
51 #include <sys/eventfd.h>
52 #include <stdint.h> /* for uint64_t */
53 #ifdef HAVE_UNISTD_H
54 #include <unistd.h> /* for read(), write(), errno */
55 #endif /* HAVE_UNISTD_H */
56 #ifdef HAVE_STRING_H
57 #include <string.h> /* for strerror() */
58 #endif
59 
60 
66 #define MHD_itc_init_(itc) (-1 != ((itc).fd = eventfd (0, EFD_CLOEXEC | EFD_NONBLOCK)))
67 
71 #define MHD_itc_last_strerror_() strerror(errno)
72 
76 static const uint64_t _MHD_itc_wr_data = 1;
77 
84 #define MHD_itc_activate_(itc, str) \
85  ((write((itc).fd, (const void*)&_MHD_itc_wr_data, 8) > 0) || (EAGAIN == errno))
86 
92 #define MHD_itc_r_fd_(itc) ((itc).fd)
93 
99 #define MHD_itc_w_fd_(itc) ((itc).fd)
100 
105 #define MHD_itc_clear_(itc) \
106  do { uint64_t __b; int __r; \
107  __r = read((itc).fd, &__b, sizeof(__b)); \
108  (void)__r; } while(0)
109 
117 #define MHD_itc_destroy_(itc) ((0 == close ((itc).fd)) || (EBADF != errno))
118 
128 #define MHD_ITC_IS_VALID_(itc) (-1 != ((itc).fd))
129 
134 #define MHD_itc_set_invalid_(itc) ((itc).fd = -1)
135 
136 
137 #elif defined(_MHD_ITC_PIPE)
138 
139 /* **************** Standard UNIX ITC implementation by pipe ********** */
140 
141 #if defined(HAVE_PIPE2_FUNC) && defined(HAVE_FCNTL_H)
142 # include <fcntl.h> /* for O_CLOEXEC, O_NONBLOCK */
143 #endif /* HAVE_PIPE2_FUNC && HAVE_FCNTL_H */
144 #ifdef HAVE_UNISTD_H
145 #include <unistd.h> /* for read(), write(), errno */
146 #endif /* HAVE_UNISTD_H */
147 #ifdef HAVE_STRING_H
148 #include <string.h> /* for strerror() */
149 #endif
150 
151 
157 #ifdef HAVE_PIPE2_FUNC
158 # define MHD_itc_init_(itc) (!pipe2((itc).fd, O_CLOEXEC | O_NONBLOCK))
159 #else /* ! HAVE_PIPE2_FUNC */
160 # define MHD_itc_init_(itc) \
161  ( (!pipe((itc).fd)) ? \
162  (MHD_itc_nonblocking_((itc)) ? \
163  (!0) : \
164  (MHD_itc_destroy_((itc)), 0) ) \
165  : (0) )
166 #endif /* ! HAVE_PIPE2_FUNC */
167 
171 #define MHD_itc_last_strerror_() strerror(errno)
172 
179 #define MHD_itc_activate_(itc, str) \
180  ((write((itc).fd[1], (const void*)(str), 1) > 0) || (EAGAIN == errno))
181 
182 
188 #define MHD_itc_r_fd_(itc) ((itc).fd[0])
189 
195 #define MHD_itc_w_fd_(itc) ((itc).fd[1])
196 
201 #define MHD_itc_clear_(itc) do \
202  { long __b; \
203  while(0 < read((itc).fd[0], &__b, sizeof(__b))) \
204  {} } while(0)
205 
211 #define MHD_itc_destroy_(itc) \
212  ( (0 == close ((itc).fd[0])) ? \
213  (0 == close ((itc).fd[1])) : \
214  ((close ((itc).fd[1])), 0) )
215 
225 #define MHD_ITC_IS_VALID_(itc) (-1 != (itc).fd[0])
226 
231 #define MHD_itc_set_invalid_(itc) ((itc).fd[0] = (itc).fd[1] = -1)
232 
233 #ifndef HAVE_PIPE2_FUNC
234 
240  int
241  MHD_itc_nonblocking_ (struct MHD_itc_ itc);
242 #endif /* ! HAVE_PIPE2_FUNC */
243 
244 
245 #elif defined(_MHD_ITC_SOCKETPAIR)
246 
247 /* **************** ITC implementation by socket pair ********** */
248 
249 #include "mhd_sockets.h"
250 
251 
257 #ifdef MHD_socket_pair_nblk_
258 # define MHD_itc_init_(itc) MHD_socket_pair_nblk_((itc).sk)
259 #else /* ! MHD_socket_pair_nblk_ */
260 # define MHD_itc_init_(itc) \
261  (MHD_socket_pair_((itc).sk) ? \
262  (MHD_itc_nonblocking_((itc)) ? \
263  (!0) : \
264  (MHD_itc_destroy_((itc)), 0) ) \
265  : (0))
266 #endif /* ! MHD_socket_pair_nblk_ */
267 
271 #define MHD_itc_last_strerror_() MHD_socket_last_strerr_()
272 
279 #define MHD_itc_activate_(itc, str) \
280  ((MHD_send_((itc).sk[1], (str), 1) > 0) || \
281  (MHD_SCKT_ERR_IS_EAGAIN_(MHD_socket_get_error_())))
282 
288 #define MHD_itc_r_fd_(itc) ((itc).sk[0])
289 
295 #define MHD_itc_w_fd_(itc) ((itc).sk[1])
296 
301 #define MHD_itc_clear_(itc) do \
302  { long __b; \
303  while(0 < recv((itc).sk[0], \
304  (char*)&__b, \
305  sizeof(__b), 0)) \
306  {} } while(0)
307 
313 #define MHD_itc_destroy_(itc) \
314  ( MHD_socket_close_((itc).sk[0]) ? \
315  MHD_socket_close_((itc).sk[1]) : \
316  ((void)MHD_socket_close_((itc).sk[1]), 0) )
317 
318 
328 #define MHD_ITC_IS_VALID_(itc) (MHD_INVALID_SOCKET != (itc).sk[0])
329 
334 #define MHD_itc_set_invalid_(itc) ((itc).sk[0] = (itc).sk[1] = MHD_INVALID_SOCKET)
335 
336 #ifndef MHD_socket_pair_nblk_
337 # define MHD_itc_nonblocking_(pip) (MHD_socket_nonblocking_((pip).sk[0]) && MHD_socket_nonblocking_((pip).sk[1]))
338 #endif /* ! MHD_socket_pair_nblk_ */
339 
340 #endif /* _MHD_ITC_SOCKETPAIR */
341 
347 #define MHD_itc_destroy_chk_(itc) do { \
348  if (!MHD_itc_destroy_(itc)) \
349  MHD_PANIC(_("Failed to destroy ITC.\n")); \
350  } while(0)
351 
361 #define MHD_ITC_IS_INVALID_(itc) (! MHD_ITC_IS_VALID_(itc))
362 
363 #endif /* MHD_ITC_H */
Types for platform-independent inter-thread communication.