2 * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3 * Copyright (C) <2004> Wim Taymans <wim@fluendo.com>
5 * gsttcpfdset.h: fdset datastructure
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the
19 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
23 #define MIN_POLLFDS 32
24 #define INIT_POLLFDS MIN_POLLFDS
28 #include <sys/types.h>
30 /* OS/X needs this because of bad headers */
36 gst_fdset_mode_get_type (void)
38 static GType fdset_mode_type = 0;
39 static GEnumValue fdset_mode[] = {
40 {GST_FDSET_MODE_SELECT, "Select", "select"},
41 {GST_FDSET_MODE_POLL, "Poll", "poll"},
42 {GST_FDSET_MODE_EPOLL, "EPoll", "epoll"},
46 if (!fdset_mode_type) {
47 fdset_mode_type = g_enum_register_static ("GstFDSetMode", fdset_mode);
49 return fdset_mode_type;
57 struct pollfd *testpollfds;
58 gint last_testpollfds;
61 struct pollfd *pollfds;
68 fd_set readfds, writefds; /* input */
69 fd_set testreadfds, testwritefds; /* output */
73 nearest_pow (gint num)
75 /* hacker's delight page 48 */
86 /* resize a given pollfd array from old_size number of items
87 * to new_size number of items. Also initializes the new elements
88 * with the default values. */
89 static struct pollfd *
90 resize (struct pollfd *fds, gint old_size, gint new_size)
95 res = g_realloc (fds, new_size * sizeof (struct pollfd));
96 for (i = old_size; i < new_size; i++) {
105 ensure_size (GstFDSet * set, gint len)
107 if (len > set->size) {
108 len = nearest_pow (len);
109 len = MAX (len, MIN_POLLFDS);
111 set->pollfds = resize (set->pollfds, set->size, len);
117 gst_fdset_new (GstFDSetMode mode)
121 nset = g_new0 (GstFDSet, 1);
125 case GST_FDSET_MODE_SELECT:
126 FD_ZERO (&nset->readfds);
127 FD_ZERO (&nset->writefds);
129 case GST_FDSET_MODE_POLL:
130 nset->pollfds = NULL;
131 nset->testpollfds = NULL;
133 nset->last_pollfds = 0;
134 nset->poll_lock = g_mutex_new ();
135 ensure_size (nset, MIN_POLLFDS);
137 case GST_FDSET_MODE_EPOLL:
138 g_warning ("implement EPOLL mode in GstFDSet");
147 gst_fdset_free (GstFDSet * set)
149 g_return_if_fail (set != NULL);
152 case GST_FDSET_MODE_SELECT:
154 case GST_FDSET_MODE_POLL:
155 g_free (set->testpollfds);
156 g_free (set->pollfds);
157 g_mutex_free (set->poll_lock);
159 case GST_FDSET_MODE_EPOLL:
160 g_warning ("implement EPOLL mode in GstFDSet");
170 gst_fdset_set_mode (GstFDSet * set, GstFDSetMode mode)
172 g_return_if_fail (set != NULL);
174 g_warning ("implement set_mode in GstFDSet");
178 gst_fdset_get_mode (GstFDSet * set)
180 g_return_val_if_fail (set != NULL, FALSE);
186 gst_fdset_add_fd (GstFDSet * set, GstFD * fd)
188 gboolean res = FALSE;
190 g_return_val_if_fail (set != NULL, FALSE);
191 g_return_val_if_fail (fd != NULL, FALSE);
194 case GST_FDSET_MODE_SELECT:
197 case GST_FDSET_MODE_POLL:
202 g_mutex_lock (set->poll_lock);
204 ensure_size (set, set->last_pollfds + 1);
208 /* find free space */
209 while (idx < set->last_pollfds) {
211 if (set->pollfds[idx].fd == -1)
215 nfd = &set->pollfds[idx];
218 nfd->events = POLLERR | POLLNVAL | POLLHUP;
221 /* see if we have one fd more */
222 set->last_pollfds = MAX (idx + 1, set->last_pollfds);
225 g_mutex_unlock (set->poll_lock);
230 case GST_FDSET_MODE_EPOLL:
237 gst_fdset_remove_fd (GstFDSet * set, GstFD * fd)
239 gboolean res = FALSE;
241 g_return_val_if_fail (set != NULL, FALSE);
242 g_return_val_if_fail (fd != NULL, FALSE);
245 case GST_FDSET_MODE_SELECT:
247 FD_CLR (fd->fd, &set->writefds);
248 FD_CLR (fd->fd, &set->readfds);
251 case GST_FDSET_MODE_POLL:
253 g_mutex_lock (set->poll_lock);
255 /* FIXME on some platforms poll doesn't ignore the fd
257 set->pollfds[fd->idx].fd = -1;
258 set->pollfds[fd->idx].events = 0;
259 set->pollfds[fd->idx].revents = 0;
261 /* if we removed the last fd, we can lower the last_pollfds */
262 if (fd->idx + 1 == set->last_pollfds) {
267 if (set->free == -1) {
270 set->free = MIN (set->free, fd->idx);
272 g_mutex_unlock (set->poll_lock);
276 case GST_FDSET_MODE_EPOLL:
283 gst_fdset_fd_ctl_write (GstFDSet * set, GstFD * fd, gboolean active)
285 g_return_if_fail (set != NULL);
286 g_return_if_fail (fd != NULL);
289 case GST_FDSET_MODE_SELECT:
291 FD_SET (fd->fd, &set->writefds);
293 FD_CLR (fd->fd, &set->writefds);
295 case GST_FDSET_MODE_POLL:
299 g_mutex_lock (set->poll_lock);
303 gint events = set->pollfds[idx].events;
310 set->pollfds[idx].events = events;
312 g_mutex_unlock (set->poll_lock);
315 case GST_FDSET_MODE_EPOLL:
321 gst_fdset_fd_ctl_read (GstFDSet * set, GstFD * fd, gboolean active)
323 g_return_if_fail (set != NULL);
324 g_return_if_fail (fd != NULL);
327 case GST_FDSET_MODE_SELECT:
329 FD_SET (fd->fd, &set->readfds);
331 FD_CLR (fd->fd, &set->readfds);
333 case GST_FDSET_MODE_POLL:
337 g_mutex_lock (set->poll_lock);
341 gint events = set->pollfds[idx].events;
344 events |= (POLLIN | POLLPRI);
346 events &= ~(POLLIN | POLLPRI);
348 set->pollfds[idx].events = events;
350 g_mutex_unlock (set->poll_lock);
353 case GST_FDSET_MODE_EPOLL:
359 gst_fdset_fd_has_closed (GstFDSet * set, GstFD * fd)
361 gboolean res = FALSE;
363 g_return_val_if_fail (set != NULL, FALSE);
364 g_return_val_if_fail (fd != NULL, FALSE);
367 case GST_FDSET_MODE_SELECT:
370 case GST_FDSET_MODE_POLL:
374 g_mutex_lock (set->poll_lock);
377 if (idx >= 0 && idx < set->last_testpollfds) {
378 res = (set->testpollfds[idx].revents & POLLHUP) != 0;
380 g_mutex_unlock (set->poll_lock);
383 case GST_FDSET_MODE_EPOLL:
390 gst_fdset_fd_has_error (GstFDSet * set, GstFD * fd)
392 gboolean res = FALSE;
394 g_return_val_if_fail (set != NULL, FALSE);
395 g_return_val_if_fail (fd != NULL, FALSE);
398 case GST_FDSET_MODE_SELECT:
401 case GST_FDSET_MODE_POLL:
405 g_mutex_lock (set->poll_lock);
408 if (idx >= 0 && idx < set->last_testpollfds) {
409 res = (set->testpollfds[idx].revents & (POLLERR | POLLNVAL)) != 0;
411 g_mutex_unlock (set->poll_lock);
414 case GST_FDSET_MODE_EPOLL:
421 gst_fdset_fd_can_read (GstFDSet * set, GstFD * fd)
423 gboolean res = FALSE;
425 g_return_val_if_fail (set != NULL, FALSE);
426 g_return_val_if_fail (fd != NULL, FALSE);
429 case GST_FDSET_MODE_SELECT:
430 res = FD_ISSET (fd->fd, &set->testreadfds);
432 case GST_FDSET_MODE_POLL:
436 g_mutex_lock (set->poll_lock);
439 if (idx >= 0 && idx < set->last_testpollfds) {
440 res = (set->testpollfds[idx].revents & (POLLIN | POLLPRI)) != 0;
442 g_mutex_unlock (set->poll_lock);
445 case GST_FDSET_MODE_EPOLL:
452 gst_fdset_fd_can_write (GstFDSet * set, GstFD * fd)
454 gboolean res = FALSE;
456 g_return_val_if_fail (set != NULL, FALSE);
457 g_return_val_if_fail (fd != NULL, FALSE);
460 case GST_FDSET_MODE_SELECT:
461 res = FD_ISSET (fd->fd, &set->testwritefds);
463 case GST_FDSET_MODE_POLL:
467 g_mutex_lock (set->poll_lock);
470 if (idx >= 0 && idx < set->last_testpollfds) {
471 res = (set->testpollfds[idx].revents & POLLOUT) != 0;
473 g_mutex_unlock (set->poll_lock);
476 case GST_FDSET_MODE_EPOLL:
483 gst_fdset_wait (GstFDSet * set, int timeout)
487 g_return_val_if_fail (set != NULL, -1);
490 case GST_FDSET_MODE_SELECT:
493 struct timeval *tvptr;
495 set->testreadfds = set->readfds;
496 set->testwritefds = set->writefds;
499 tv.tv_sec = timeout / 1000;
500 tv.tv_usec = timeout % 1000;
507 select (FD_SETSIZE, &set->testreadfds, &set->testwritefds,
508 (fd_set *) 0, tvptr);
511 case GST_FDSET_MODE_POLL:
513 g_mutex_lock (set->poll_lock);
514 if (set->testsize != set->size) {
515 set->testpollfds = resize (set->testpollfds, set->testsize, set->size);
516 set->testsize = set->size;
518 set->last_testpollfds = set->last_pollfds;
519 memcpy (set->testpollfds, set->pollfds,
520 sizeof (struct pollfd) * set->last_testpollfds);
521 g_mutex_unlock (set->poll_lock);
523 res = poll (set->testpollfds, set->last_testpollfds, timeout);
527 case GST_FDSET_MODE_EPOLL: