* Copyright (C) 1999 Erik Walthinsen <omega@cse.ogi.edu>
* Copyright (C) 2004 Wim Taymans <wim.taymans@gmail.com>
* Copyright (C) 2007 Peter Kjellerstedt <pkj@axis.com>
- * Copyright (C) 2008 Ole André Vadla Ravnås <ole.andre.ravnas@tandberg.com>
+ * Copyright (C) 2008 Ole André Vadla Ravnås <ole.andre.ravnas@tandberg.com>
*
* gstpoll.c: File descriptor set
*
*/
/**
* SECTION:gstpoll
+ * @title: GstPoll
* @short_description: Keep track of file descriptors and make it possible
* to wait on them in a cancellable way
*
* New file descriptors are added to the set using gst_poll_add_fd(), and
* removed using gst_poll_remove_fd(). Controlling which file descriptors
* should be waited for to become readable and/or writable are done using
- * gst_poll_fd_ctl_read() and gst_poll_fd_ctl_write().
+ * gst_poll_fd_ctl_read(), gst_poll_fd_ctl_write() and gst_poll_fd_ctl_pri().
*
* Use gst_poll_wait() to wait for the file descriptors to actually become
* readable and/or writable, or to timeout if no file descriptor is available
#include <sys/socket.h>
#endif
+#ifdef G_OS_WIN32
+# ifndef EWOULDBLOCK
+# define EWOULDBLOCK EAGAIN /* This is just to placate gcc */
+# endif
+#endif /* G_OS_WIN32 */
+
/* OS/X needs this because of bad headers */
#include <string.h>
DWORD status;
SetLastError (0);
errno = 0;
- if (status = WaitForSingleObject (set->wakeup_event, INFINITE)) {
+
+ status = WaitForSingleObject (set->wakeup_event, INFINITE);
+ if (status) {
const gchar *reason = "unknown";
gchar msg[1024] = "<unknown>";
switch (status) {
* timeouts.
*
* A timeout is performed with gst_poll_wait(). Multiple timeouts can be
- * performed from different threads.
+ * performed from different threads.
*
* Free-function: gst_poll_free
*
struct pollfd *pfd = &g_array_index (set->fds, struct pollfd, idx);
if (active)
- pfd->events |= (POLLIN | POLLPRI);
+ pfd->events |= POLLIN;
else
- pfd->events &= ~(POLLIN | POLLPRI);
+ pfd->events &= ~POLLIN;
#else
gst_poll_update_winsock_event_mask (set, idx, FD_READ | FD_ACCEPT, active);
#endif
}
/**
+ * gst_poll_fd_ctl_pri:
+ * @set: a file descriptor set.
+ * @fd: a file descriptor.
+ * @active: a new status.
+ *
+ * Control whether the descriptor @fd in @set will be monitored for
+ * exceptional conditions (POLLPRI).
+ *
+ * Not implemented on Windows (will just return %FALSE there).
+ *
+ * Returns: %TRUE if the descriptor was successfully updated.
+ *
+ * Since: 1.16
+ */
+gboolean
+gst_poll_fd_ctl_pri (GstPoll * set, GstPollFD * fd, gboolean active)
+{
+#ifdef G_OS_WIN32
+ return FALSE;
+#else
+ gint idx;
+
+ g_return_val_if_fail (set != NULL, FALSE);
+ g_return_val_if_fail (fd != NULL, FALSE);
+ g_return_val_if_fail (fd->fd >= 0, FALSE);
+
+ GST_DEBUG ("%p: fd (fd:%d, idx:%d), active : %d", set,
+ fd->fd, fd->idx, active);
+
+ g_mutex_lock (&set->lock);
+
+ idx = find_index (set->fds, fd);
+ if (idx >= 0) {
+ struct pollfd *pfd = &g_array_index (set->fds, struct pollfd, idx);
+
+ if (active)
+ pfd->events |= POLLPRI;
+ else
+ pfd->events &= ~POLLPRI;
+
+ GST_LOG ("%p: pfd->events now %d (POLLPRI:%d)", set, pfd->events, POLLOUT);
+ MARK_REBUILD (set);
+ } else {
+ GST_WARNING ("%p: couldn't find fd !", set);
+ }
+
+ g_mutex_unlock (&set->lock);
+
+ return idx >= 0;
+#endif
+}
+
+/**
* gst_poll_fd_ignored:
* @set: a file descriptor set.
* @fd: a file descriptor.
#ifndef G_OS_WIN32
struct pollfd *pfd = &g_array_index (set->active_fds, struct pollfd, idx);
- res = (pfd->revents & (POLLIN | POLLPRI)) != 0;
+ res = (pfd->revents & POLLIN) != 0;
#else
WinsockFd *wfd = &g_array_index (set->active_fds, WinsockFd, idx);
}
/**
+ * gst_poll_fd_has_pri:
+ * @set: a file descriptor set.
+ * @fd: a file descriptor.
+ *
+ * Check if @fd in @set has an exceptional condition (POLLPRI).
+ *
+ * Not implemented on Windows (will just return %FALSE there).
+ *
+ * Returns: %TRUE if the descriptor has an exceptional condition.
+ *
+ * Since: 1.16
+ */
+gboolean
+gst_poll_fd_has_pri (const GstPoll * set, GstPollFD * fd)
+{
+#ifdef G_OS_WIN32
+ return FALSE;
+#else
+ gboolean res = FALSE;
+ gint idx;
+
+ g_return_val_if_fail (set != NULL, FALSE);
+ g_return_val_if_fail (fd != NULL, FALSE);
+ g_return_val_if_fail (fd->fd >= 0, FALSE);
+
+ g_mutex_lock (&((GstPoll *) set)->lock);
+
+ idx = find_index (set->active_fds, fd);
+ if (idx >= 0) {
+ struct pollfd *pfd = &g_array_index (set->active_fds, struct pollfd, idx);
+
+ res = (pfd->revents & POLLPRI) != 0;
+ } else {
+ GST_WARNING ("%p: couldn't find fd !", set);
+ }
+ g_mutex_unlock (&((GstPoll *) set)->lock);
+
+ GST_DEBUG ("%p: fd (fd:%d, idx:%d) %d", set, fd->fd, fd->idx, res);
+
+ return res;
+#endif
+}
+
+/**
* gst_poll_wait:
* @set: a #GstPoll.
* @timeout: a timeout in nanoseconds.
*
* Write a byte to the control socket of the controllable @set.
* This function is mostly useful for timer #GstPoll objects created with
- * gst_poll_new_timer().
+ * gst_poll_new_timer().
*
* It will make any current and future gst_poll_wait() function return with
* 1, meaning the control socket is set. After an equal amount of calls to
* This function only works for timer #GstPoll objects created with
* gst_poll_new_timer().
*
- * Returns: %TRUE on success. %FALSE when @set is not controllable or when the
- * byte could not be written.
+ * Returns: %TRUE on success. %FALSE when when the byte could not be written.
+ * errno contains the detailed error code but will never be EAGAIN, EINTR or
+ * EWOULDBLOCK. %FALSE always signals a critical error.
*/
gboolean
gst_poll_write_control (GstPoll * set)
* This function only works for timer #GstPoll objects created with
* gst_poll_new_timer().
*
- * Returns: %TRUE on success. %FALSE when @set is not controllable or when there
- * was no byte to read.
+ * Returns: %TRUE on success. %FALSE when when there was no byte to read or
+ * reading the byte failed. If there was no byte to read, and only then, errno
+ * will contain EWOULDBLOCK or EAGAIN. For all other values of errno this always signals a
+ * critical error.
*/
gboolean
gst_poll_read_control (GstPoll * set)