Re: Data available for reading in a GIOChannel



Looking at the glib source here:

glib/giochannel.c
glib/giochannel.h
glib/giounix.c

You can see that, at least on a *nix machine, g_io_channel_read_chars()
calls the c library read() on a file descriptor in the GIOChannel
struct.  The segment:

----------------------------------------------------------------
  result = read (unix_channel->fd, buf, count);

  if (result < 0)
    {
      *bytes_read = 0;

      switch (errno)
        {
#ifdef EINTR
          case EINTR:
            goto retry;
#endif
#ifdef EAGAIN
          case EAGAIN:
            return G_IO_STATUS_AGAIN;
#endif
----------------------------------------------------------------

So, basically, on a Linux (or presumably any *nix like OS) the semantics
of g_io_channel_read_chars() will be roughly the same as POSIX read()*.
You can see that when read() returns -1 (< 0), and the global errno is
set to EAGAIN then G_IO_STATUS_AGAIN is returned.

read() is a system call.  Last I checked (a long, long time ago) EAGAIN
is set in the kernel side of the read() call when there is no data in
the buffer to read.  Unless I'm mistaken, the only way, in *nix land, to
hear from the kernel again about there being more data, is to call
select(), poll(), or read() again...  or to handle SIGIO while using
signal-driven IO (see O_ASYNC in the open(2) man page and*).

The g_io_channels appear to use poll() if a built-in system version is
available, and to emulate poll(), if it's not.  So, I believe the
semantics, on *nix at least, more or less amount to:

while( poll() )  /* glib main loop does this */
{
    read();      /* your callback does this */
}


I don't see any magic happening that might make it more complicated.  If
you're using threads then it does get more complicated, but not in any
way that can't be managed by typical thread management.  Also, the
functions that are actually used to do the reading are set as callbacks
in the GIOChannel struct.  Default calls the standard unix read(), but
if you're working on someone else's code...  you may want to double
check that.

I have never done IO on a win32 or...  really on any non-*nix machine,
so my experience is a bit limited.  As I understand it though, glib/gtk+
work at making the differences as small as possible.  I would not expect
a significant difference in how the g_io_channel interface behaves.

- Ana



* if you haven't already read it: "Advanced Programming in the UNIX
Environment", by W. Richard Stevens is a good book to keep around.

On Tue, May 29, 2007 at 10:20:20PM +0200, Jonathan Winterflood wrote:
>    Thanks for your precisions on where this difference comes from :)
> 
>    I guess   g_io_channel_set_flags(_channel, G_IO_FLAG_NONBLOCK, NULL);  is
>    good for switching to non-blocking mode.
> 
>    A question arises, though: is it possible that the channel will recieve
>    the last of the data between the
>    time  g_io_channel_read_chars  returns G_IO_STATUS_AGAIN and the callback exits, and that the callback will not be called again?
> 
>    This would be a really easy way to get stuck waiting for data which is
>    already there, so I'm thinking no, can you confirm this?
> 
>    Thanks a lot,
>    Jonathan
> 
>    On 5/29/07, Paul Davis <[1]paul linuxaudiosystems com> wrote:
> 
>      On Mon, 2007-05-28 at 17:26 +0200, Jonathan Winterflood wrote:
>      > Hi,
>      >
>      > > you never know how much readable data is available until you read
>      > it, you are only ever guaranteed to have one byte of data available
>      > for reading anyway.
>      >
>      > In my opinion, the channel should _always_ know how much data is
>      > available, how can it tell that there is nothing there?... Plus, it
>      > can't not know the amount of data it _has_ actually recieved and is
>      > buffered ready for me...
> 
>      there is a very big difference between knowing the distinctions between:
> 
>         * something and nothing
>         * specifically how much and nothing at all
> 
>      the process that leads to the callback is called as soon as a single
>      byte of data arrives. there might be more data by the time it actually
>      executes. nothing else in the system (except perhaps a device driver) is
>      buffering data for you and then saying (post-facto) "we have some
>      stuff". your callback can do that if it wants to offer that kind of
>      service to high level layers of your application/code.
> 
>      > Java InputStreams for example have the available() method:
>      >
>      [2]http://java.sun.com/javase/6/docs/api/java/io/InputStream.html#available()
> 
>      thats because Java InputStreams are heavily buffered. glib/gtk
>      IOChannels are not, by default. in particular, when you use this
>      callback method, your code is being notified that there is data
>      available long before a Java InputStream would have told that it had
>      information ready.
> 
>      > > [...] I read the data in 1024 byte chunks [...]
>      > This sounds like a good workaround, which will work well in a watch
>      > callback; I'll use that
> 
>      the important thing is just to use non-blocking I/O with the channel. t
> 
>    --
>    <Morpheus> linux, c'est une question de VI ou de MORE
> 
> References
> 
>    Visible links
>    1. mailto:paul linuxaudiosystems com
>    2. http://java.sun.com/javase/6/docs/api/java/io/InputStream.html#available()

> _______________________________________________
> gtk-list mailing list
> gtk-list gnome org
> http://mail.gnome.org/mailman/listinfo/gtk-list




[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]