Re: Data available for reading in a GIOChannel



On 5/28/07, Ana <christiana hipointcoffee com> wrote:
On Mon, May 28, 2007 at 04:42:11PM -0300, Alexandre Moreira wrote:
> On 5/28/07, Robert Pearce <rob bdt-home demon co uk> wrote:
> > On Sun, 27 May 2007 16:57:03 +0200 Jonathan wrote:
> > > Hi,
> > >
> > > I need to read a large amount of data from a GIOChannel (200K, over
> > > the internet).
> > >
> > > So far, I use the gnet library to create the
> > > socket, and then I use the GIOChannel to integrate the read/writing
> > > into the program's loop (a
> > > GTK application)
> > >
> > > I use g_io_add_watch(_channel, G_IO_IN, &(_imageDataReadyForReading), this);
> > > to register the callback for data reading.
> > >
> > > How can I determine the number of bytes available for reading, so as not to
> > > block on reading the data?
> > >
> >
> > On the applications where I've used g_io_add_watch it's on a serial port that I've opened non-blocking. Then my callback I just does:
> >     stat = g_io_channel_read_chars ( source,
> >                                      tmpbuf, sizeof(tmpbuf), &len, &err );
> >
> > If there are less than tmpbuf characters waiting, it fills what it can and sets len to the actual number. Then I process len bytes. Normally my tmpbuf is bigger than the longest message I expect, but it seems to work even if it isn't.
>
> Please anyone correct me if I'm wrong, but...
>
> I guess you should loop until EAGAIN,  because you can get some nasty
> things if your program is being run on a system where the select (or
> poll, or whatever it uses to watch the channels) call returns when the
> file descriptor CHANGES its state (ready to read // not ready to
> read).

That's what I typically do.  something like this:

/* make sure 'source' is non-blocking before entering loop
 * below is simplified */
do {
  len = 0;
  stat = g_io_channel_read_chars ( source,
                                   tmpbuf, sizeof(tmpbuf), &len, &err );
  if( len > 0 )
    process_data(tmpbuf, len);
 } while(stat == G_IO_STATUS_NORMAL && len == sizeof(tmpbuf));


Whether it's necessary or advisable to read in a loop like that, I'm not
sure.  Depending on certain things, such how long the process_data()
function takes, you may wish to let the main loop run after every time
process_data() is called...  in which case you wouldn't use a loop like
the above.


> In that case you could create a situation where a client is expecting
> for some response from you, but you didn't actually read the request
> (because it is lost in the buffer) and therefore each process is
> waiting for the other to act.

I think the question here is: if we don't read all available data before
returning to poll/select, will our callback be triggered again so that
we can process the remaining data?  Without doing any research, I
believe the answer would have to be 'yes'.  To make sure, look at some
source or create a test.

Perhaps I didn't express myself well enough. But I'll try to be clearer now.

That was pretty much what I was talking about: I don't know about
Glib's IO Channels, but there are certain facilities (epoll on linux,
for example, IIRC) which let's the programmer choose which kind of
behavior it'll have: level based (if exists data to be read it will
return with the result) or edge based (whenever it goes from not
having data to be read to having data to be read it'll return with the
result).

What I mean was, depending on what stuff glib uses on certain
architectures, it could behave in a way that the problem I mentioned
would be relevant. As such, I find safer to read stuff until it tells
me it would block (Ok, there is the possibility of a starvation there,
but I don't write this kind of code often enough to worry about it...
I should really give the subject a bit more study/thought.)

Regards,
Alexandre Moreira.


- Ana

_______________________________________________
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]