configure.ac: Add checks for poll, ppoll and pselect.

Original commit message from CVS:
* configure.ac:
Add checks for poll, ppoll and pselect.
* docs/gst/gstreamer-docs.sgml:
* docs/gst/gstreamer-sections.txt:
Add docs for GstPoll.
* gst/Makefile.am:
* gst/gst.h:
* gst/gstpoll.c: (find_index), (selectable_fds),
(pollable_timeout), (choose_mode), (pollfd_to_fd_set),
(fd_set_to_pollfd), (gst_poll_new), (gst_poll_free),
(gst_poll_set_mode), (gst_poll_get_mode),
(gst_poll_add_fd_unlocked), (gst_poll_add_fd),
(gst_poll_remove_fd), (gst_poll_fd_ctl_write),
(gst_poll_fd_ctl_read_unlocked), (gst_poll_fd_ctl_read),
(gst_poll_fd_has_closed), (gst_poll_fd_has_error),
(gst_poll_fd_can_read_unlocked), (gst_poll_fd_can_read),
(gst_poll_fd_can_write), (gst_poll_wait),
(gst_poll_set_controllable), (gst_poll_restart),
(gst_poll_set_flushing):
* gst/gstpoll.h:
Add generic poll abstraction. We ideally don't want to have this in core
here but in glib intead...
This code will be used in various network elements and ultimately for
the nanosecond precision monotonic clock (that's why it's here in core).
It'll allow us to implement cancelable socket operations for windows too.
* tests/check/Makefile.am:
* tests/check/gst/gstpoll.c: (test_poll_wait), (GST_START_TEST),
(delayed_stop), (delayed_restart), (delayed_flush),
(delayed_control), (gst_poll_suite):
Add GstPoll unit test.
This commit is contained in:
Wim Taymans 2008-02-27 18:00:04 +00:00
parent ef4fb687a9
commit d37ee60f47
11 changed files with 1567 additions and 1 deletions

View file

@ -1,3 +1,39 @@
2008-02-27 Wim Taymans <wim.taymans@collabora.co.uk>
* configure.ac:
Add checks for poll, ppoll and pselect.
* docs/gst/gstreamer-docs.sgml:
* docs/gst/gstreamer-sections.txt:
Add docs for GstPoll.
* gst/Makefile.am:
* gst/gst.h:
* gst/gstpoll.c: (find_index), (selectable_fds),
(pollable_timeout), (choose_mode), (pollfd_to_fd_set),
(fd_set_to_pollfd), (gst_poll_new), (gst_poll_free),
(gst_poll_set_mode), (gst_poll_get_mode),
(gst_poll_add_fd_unlocked), (gst_poll_add_fd),
(gst_poll_remove_fd), (gst_poll_fd_ctl_write),
(gst_poll_fd_ctl_read_unlocked), (gst_poll_fd_ctl_read),
(gst_poll_fd_has_closed), (gst_poll_fd_has_error),
(gst_poll_fd_can_read_unlocked), (gst_poll_fd_can_read),
(gst_poll_fd_can_write), (gst_poll_wait),
(gst_poll_set_controllable), (gst_poll_restart),
(gst_poll_set_flushing):
* gst/gstpoll.h:
Add generic poll abstraction. We ideally don't want to have this in core
here but in glib intead...
This code will be used in various network elements and ultimately for
the nanosecond precision monotonic clock (that's why it's here in core).
It'll allow us to implement cancelable socket operations for windows too.
* tests/check/Makefile.am:
* tests/check/gst/gstpoll.c: (test_poll_wait), (GST_START_TEST),
(delayed_stop), (delayed_restart), (delayed_flush),
(delayed_control), (gst_poll_suite):
Add GstPoll unit test.
2008-02-25 Tim-Philipp Müller <tim at centricular dot net>
* gst/gstfilter.c:

2
common

@ -1 +1 @@
Subproject commit a574e6214b06fcbdfc00e952e2f3edc06997ee93
Subproject commit e746d20ef536a73aea9964666c7d5f6d5c9465df

View file

@ -341,6 +341,11 @@ AC_CHECK_FUNCS([ftello])
AC_CHECK_FUNCS([fgetpos])
AC_CHECK_FUNCS([fsetpos])
dnl check for poll(), ppoll() and pselect()
AC_CHECK_FUNCS([poll])
AC_CHECK_FUNCS([ppoll])
AC_CHECK_FUNCS([pselect])
dnl check for mmap()
AC_FUNC_MMAP
AM_CONDITIONAL(HAVE_MMAP, test "x$ac_cv_func_mmap_fixed_mapped" = "xyes")

View file

@ -35,6 +35,7 @@
<!ENTITY GstPipeline SYSTEM "xml/gstpipeline.xml">
<!ENTITY GstPlugin SYSTEM "xml/gstplugin.xml">
<!ENTITY GstPluginFeature SYSTEM "xml/gstpluginfeature.xml">
<!ENTITY GstPoll SYSTEM "xml/gstpoll.xml">
<!ENTITY GstQuery SYSTEM "xml/gstquery.xml">
<!ENTITY GstRegistry SYSTEM "xml/gstregistry.xml">
<!ENTITY GstSegment SYSTEM "xml/gstsegment.xml">
@ -138,6 +139,7 @@ Windows. It is released under the GNU Library General Public License
&GstPipeline;
&GstPlugin;
&GstPluginFeature;
&GstPoll;
&GstQuery;
&GstRegistry;
&GstSegment;

View file

@ -1604,6 +1604,35 @@ gst_rank_get_type
</SECTION>
<SECTION>
<FILE>gstpoll</FILE>
<TITLE>GstPoll</TITLE>
GstPoll
GstPollFD
GstPollMode
gst_poll_add_fd
gst_poll_fd_can_read
gst_poll_fd_can_write
gst_poll_fd_ctl_read
gst_poll_fd_ctl_write
gst_poll_fd_has_closed
gst_poll_fd_has_error
gst_poll_free
gst_poll_get_mode
gst_poll_new
gst_poll_remove_fd
gst_poll_restart
gst_poll_set_controllable
gst_poll_set_flushing
gst_poll_set_mode
gst_poll_wait
<SUBSECTION Standard>
GST_TYPE_POLL_MODE
<SUBSECTION Private>
gst_poll_mode_get_type
</SECTION>
<SECTION>
<FILE>gstquery</FILE>
<TITLE>GstQuery</TITLE>

View file

@ -102,6 +102,7 @@ libgstreamer_@GST_MAJORMINOR@_la_SOURCES = \
gstpipeline.c \
gstplugin.c \
gstpluginfeature.c \
gstpoll.c \
gstquark.c \
gstquery.c \
gstregistry.c \
@ -185,6 +186,7 @@ gst_headers = \
gstpipeline.h \
gstplugin.h \
gstpluginfeature.h \
gstpoll.h \
gstquery.h \
gstsegment.h \
gststructure.h \

View file

@ -54,6 +54,7 @@
#include <gst/gstparamspecs.h>
#include <gst/gstpipeline.h>
#include <gst/gstplugin.h>
#include <gst/gstpoll.h>
#include <gst/gstquery.h>
#include <gst/gstregistry.h>
#include <gst/gstsegment.h>

1019
gst/gstpoll.c Normal file

File diff suppressed because it is too large Load diff

97
gst/gstpoll.h Normal file
View file

@ -0,0 +1,97 @@
/* GStreamer
* 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>
*
* gstpoll.h: File descriptor set
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef __GST_POLL_H__
#define __GST_POLL_H__
#include <glib.h>
#include <glib-object.h>
#include <gst/gstclock.h>
G_BEGIN_DECLS
/**
* GstPoll:
*
* A set of file descriptors.
*/
typedef struct _GstPoll GstPoll;
/**
* GstPollFD:
* @fd: a file descriptor
*
* A file descriptor object.
*/
typedef struct {
int fd;
/*< private >*/
gint idx;
} GstPollFD;
/**
* GstPollMode:
* @GST_POLL_MODE_AUTO: choose method automatically
* @GST_POLL_MODE_SELECT: use select() when waiting
* @GST_POLL_MODE_PSELECT: use pselect() when waiting
* @GST_POLL_MODE_POLL: use poll() when waiting
* @GST_POLL_MODE_PPOLL: use ppoll() when waiting
*
* Which method to use when waiting for a set of file descriptors.
*/
typedef enum {
GST_POLL_MODE_AUTO,
GST_POLL_MODE_SELECT,
GST_POLL_MODE_PSELECT,
GST_POLL_MODE_POLL,
GST_POLL_MODE_PPOLL
} GstPollMode;
GstPoll* gst_poll_new (GstPollMode mode, gboolean controllable);
void gst_poll_free (GstPoll *set);
void gst_poll_set_mode (GstPoll *set, GstPollMode mode);
GstPollMode gst_poll_get_mode (const GstPoll *set);
gboolean gst_poll_add_fd (GstPoll *set, GstPollFD *fd);
gboolean gst_poll_remove_fd (GstPoll *set, GstPollFD *fd);
gboolean gst_poll_fd_ctl_write (GstPoll *set, GstPollFD *fd, gboolean active);
gboolean gst_poll_fd_ctl_read (GstPoll *set, GstPollFD *fd, gboolean active);
gboolean gst_poll_fd_has_closed (const GstPoll *set, GstPollFD *fd);
gboolean gst_poll_fd_has_error (const GstPoll *set, GstPollFD *fd);
gboolean gst_poll_fd_can_read (const GstPoll *set, GstPollFD *fd);
gboolean gst_poll_fd_can_write (const GstPoll *set, GstPollFD *fd);
gint gst_poll_wait (GstPoll *set, GstClockTime timeout);
gboolean gst_poll_set_controllable (GstPoll *set, gboolean controllable);
void gst_poll_restart (GstPoll *set);
void gst_poll_set_flushing (GstPoll *set, gboolean flushing);
G_END_DECLS
#endif /* __GST_POLL_H__ */

View file

@ -81,6 +81,7 @@ check_PROGRAMS = \
gst/gstobject \
gst/gstpad \
gst/gstparamspecs \
gst/gstpoll \
gst/gstsegment \
gst/gstsystemclock \
gst/gststructure \

374
tests/check/gst/gstpoll.c Normal file
View file

@ -0,0 +1,374 @@
/* GStreamer
*
* unit test for GstPoll
*
* Copyright (C) <2007> Peter Kjellerstedt <pkj@axis.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include <unistd.h>
#include <gst/check/gstcheck.h>
#ifdef G_OS_WIN32
#include <winsock2.h>
#define EINPROGRESS WSAEINPROGRESS
#else
#include <sys/socket.h>
#endif
static void
test_poll_wait (GstPollMode mode)
{
GstPoll *set;
GstPollFD rfd;
GstPollFD wfd;
gint socks[2];
guchar c = 'A';
set = gst_poll_new (mode, FALSE);
fail_if (set == NULL, "Failed to create a GstPoll");
#ifdef G_OS_WIN32
fail_if (_pipe (socks, 4096, _O_BINARY) < 0, "Could not create a pipe");
#else
fail_if (socketpair (PF_UNIX, SOCK_STREAM, 0, socks) < 0,
"Could not create a pipe");
#endif
rfd.fd = socks[0];
wfd.fd = socks[1];
fail_unless (gst_poll_add_fd (set, &rfd), "Could not add read descriptor");
fail_unless (gst_poll_fd_ctl_read (set, &rfd, TRUE),
"Could not mark the descriptor as readable");
fail_unless (write (wfd.fd, &c, 1) == 1, "write() failed");
fail_unless (gst_poll_wait (set, GST_CLOCK_TIME_NONE) == 1,
"One descriptor should be available");
fail_unless (gst_poll_fd_can_read (set, &rfd),
"Read descriptor should be readable");
fail_if (gst_poll_fd_can_write (set, &rfd),
"Read descriptor should not be writeable");
fail_unless (gst_poll_add_fd (set, &wfd), "Could not add write descriptor");
fail_unless (gst_poll_fd_ctl_write (set, &wfd, TRUE),
"Could not mark the descriptor as writeable");
fail_unless (gst_poll_wait (set, GST_CLOCK_TIME_NONE) == 2,
"Two descriptors should be available");
fail_unless (gst_poll_fd_can_read (set, &rfd),
"Read descriptor should be readable");
fail_if (gst_poll_fd_can_write (set, &rfd),
"Read descriptor should not be writeable");
fail_if (gst_poll_fd_can_read (set, &wfd),
"Write descriptor should not be readable");
fail_unless (gst_poll_fd_can_write (set, &wfd),
"Write descriptor should be writeable");
fail_unless (read (rfd.fd, &c, 1) == 1, "read() failed");
fail_unless (gst_poll_wait (set, GST_CLOCK_TIME_NONE) == 1,
"One descriptor should be available");
fail_if (gst_poll_fd_can_read (set, &rfd),
"Read descriptor should not be readable");
fail_if (gst_poll_fd_can_write (set, &rfd),
"Read descriptor should not be writeable");
fail_if (gst_poll_fd_can_read (set, &wfd),
"Write descriptor should not be readable");
fail_unless (gst_poll_fd_can_write (set, &wfd),
"Write descriptor should be writeable");
gst_poll_free (set);
close (socks[0]);
close (socks[1]);
}
GST_START_TEST (test_poll_basic)
{
GstPoll *set;
GstPollFD fd = {.fd = 1 };
set = gst_poll_new (GST_POLL_MODE_AUTO, FALSE);
fail_if (set == NULL, "Failed to create a GstPoll");
fail_unless (gst_poll_get_mode (set) == GST_POLL_MODE_AUTO,
"Mode should have been GST_POLL_MODE_AUTO");
gst_poll_set_mode (set, GST_POLL_MODE_SELECT);
fail_unless (gst_poll_get_mode (set) == GST_POLL_MODE_SELECT,
"Mode should have been GST_POLL_MODE_SELECT");
fail_unless (gst_poll_add_fd (set, &fd), "Could not add descriptor");
fail_unless (gst_poll_fd_ctl_write (set, &fd, TRUE),
"Could not mark the descriptor as writeable");
fail_unless (gst_poll_fd_ctl_read (set, &fd, TRUE),
"Could not mark the descriptor as readable");
fail_if (gst_poll_fd_has_closed (set, &fd),
"Descriptor should not be closed");
fail_if (gst_poll_fd_has_error (set, &fd),
"Descriptor should not have an error");
fail_if (gst_poll_fd_can_write (set, &fd),
"Descriptor should not be writeable");
fail_if (gst_poll_fd_can_read (set, &fd),
"Descriptor should not be readable");
fail_unless (gst_poll_remove_fd (set, &fd), "Could not remove descriptor");
fail_if (gst_poll_remove_fd (set, &fd),
"Could remove already removed descriptor");
fail_unless (gst_poll_wait (set, 50 * GST_MSECOND) == 0,
"Waiting did not timeout");
gst_poll_free (set);
set = gst_poll_new (GST_POLL_MODE_AUTO, TRUE);
fail_if (set == NULL, "Failed to create a GstPoll");
gst_poll_set_flushing (set, TRUE);
gst_poll_free (set);
}
GST_END_TEST;
static gpointer
delayed_stop (gpointer data)
{
GstPoll *set = data;
THREAD_START ();
g_usleep (500000);
gst_poll_set_flushing (set, TRUE);
return NULL;
}
GST_START_TEST (test_poll_wait_stop)
{
GstPoll *set;
set = gst_poll_new (GST_POLL_MODE_AUTO, TRUE);
fail_if (set == NULL, "Failed to create a GstPoll");
MAIN_START_THREADS (1, delayed_stop, set);
fail_unless (gst_poll_wait (set, GST_SECOND) != 0, "Waiting timed out");
MAIN_STOP_THREADS ();
gst_poll_free (set);
}
GST_END_TEST;
static gpointer
delayed_restart (gpointer data)
{
GstPoll *set = data;
GstPollFD fd = {.fd = 1 };
THREAD_START ();
g_usleep (500000);
gst_poll_add_fd (set, &fd);
gst_poll_fd_ctl_write (set, &fd, TRUE);
gst_poll_restart (set);
return NULL;
}
GST_START_TEST (test_poll_wait_restart)
{
GstPoll *set;
GstPollFD fd = {.fd = 1 };
set = gst_poll_new (GST_POLL_MODE_AUTO, TRUE);
fail_if (set == NULL, "Failed to create a GstPoll");
MAIN_START_THREADS (1, delayed_restart, set);
fail_unless (gst_poll_wait (set, GST_SECOND) > 0, "Waiting was interrupted");
fail_unless (gst_poll_fd_can_write (set, &fd),
"Write descriptor should be writeable");
MAIN_STOP_THREADS ();
gst_poll_free (set);
}
GST_END_TEST;
static gpointer
delayed_flush (gpointer data)
{
GstPoll *set = data;
THREAD_START ();
g_usleep (500000);
gst_poll_set_flushing (set, TRUE);
return NULL;
}
GST_START_TEST (test_poll_wait_flush)
{
GstPoll *set;
set = gst_poll_new (GST_POLL_MODE_AUTO, TRUE);
fail_if (set == NULL, "Failed to create a GstPoll");
gst_poll_set_flushing (set, TRUE);
fail_unless (gst_poll_wait (set, GST_SECOND) == -1 && errno == EBUSY,
"Waiting was not flushed");
fail_unless (gst_poll_wait (set, GST_SECOND) == -1 && errno == EBUSY,
"Waiting was not flushed");
gst_poll_set_flushing (set, FALSE);
fail_unless (gst_poll_wait (set, GST_SECOND) == 0, "Waiting did not timeout");
MAIN_START_THREADS (1, delayed_flush, set);
fail_unless (gst_poll_wait (set, GST_SECOND) == -1 && errno == EBUSY,
"Waiting was not flushed");
fail_unless (gst_poll_wait (set, GST_SECOND) == -1 && errno == EBUSY,
"Waiting was not flushed");
gst_poll_set_flushing (set, FALSE);
fail_unless (gst_poll_wait (set, GST_SECOND) == 0, "Waiting did not timeout");
MAIN_STOP_THREADS ();
gst_poll_free (set);
}
GST_END_TEST;
static gpointer
delayed_control (gpointer data)
{
GstPoll *set = data;
GstPollFD fd = {.fd = 1 };
THREAD_START ();
g_usleep (500000);
gst_poll_add_fd (set, &fd);
gst_poll_fd_ctl_write (set, &fd, TRUE);
gst_poll_restart (set);
THREAD_SYNCHRONIZE ();
g_usleep (500000);
gst_poll_add_fd (set, &fd);
gst_poll_fd_ctl_write (set, &fd, TRUE);
gst_poll_restart (set);
return NULL;
}
GST_START_TEST (test_poll_controllable)
{
GstPoll *set;
GstPollFD fd = {.fd = 1 };
set = gst_poll_new (GST_POLL_MODE_AUTO, FALSE);
fail_if (set == NULL, "Failed to create a GstPoll");
MAIN_START_THREADS (1, delayed_control, set);
fail_unless (gst_poll_wait (set, GST_SECOND) == 0, "Waiting did not timeout");
fail_unless (gst_poll_remove_fd (set, &fd), "Could not remove descriptor");
fail_unless (gst_poll_set_controllable (set, TRUE),
"Could not make the set controllable");
MAIN_SYNCHRONIZE ();
fail_unless (gst_poll_wait (set, GST_SECOND) > 0, "Waiting was interrupted");
fail_unless (gst_poll_fd_can_write (set, &fd),
"Write descriptor should be writeable");
MAIN_STOP_THREADS ();
gst_poll_free (set);
}
GST_END_TEST;
GST_START_TEST (test_poll_wait_auto)
{
test_poll_wait (GST_POLL_MODE_AUTO);
}
GST_END_TEST;
GST_START_TEST (test_poll_wait_ppoll)
{
test_poll_wait (GST_POLL_MODE_PPOLL);
}
GST_END_TEST;
GST_START_TEST (test_poll_wait_poll)
{
test_poll_wait (GST_POLL_MODE_POLL);
}
GST_END_TEST;
GST_START_TEST (test_poll_wait_pselect)
{
test_poll_wait (GST_POLL_MODE_PSELECT);
}
GST_END_TEST;
GST_START_TEST (test_poll_wait_select)
{
test_poll_wait (GST_POLL_MODE_SELECT);
}
GST_END_TEST;
Suite *
gst_poll_suite (void)
{
Suite *s = suite_create ("GstPoll");
TCase *tc_chain = tcase_create ("general");
/* turn off timeout */
tcase_set_timeout (tc_chain, 60);
suite_add_tcase (s, tc_chain);
tcase_add_test (tc_chain, test_poll_basic);
tcase_add_test (tc_chain, test_poll_wait_auto);
tcase_add_test (tc_chain, test_poll_wait_ppoll);
tcase_add_test (tc_chain, test_poll_wait_poll);
tcase_add_test (tc_chain, test_poll_wait_pselect);
tcase_add_test (tc_chain, test_poll_wait_select);
tcase_add_test (tc_chain, test_poll_wait_stop);
tcase_add_test (tc_chain, test_poll_wait_restart);
tcase_add_test (tc_chain, test_poll_wait_flush);
tcase_add_test (tc_chain, test_poll_controllable);
return s;
}
GST_CHECK_MAIN (gst_poll);