Re: Data available for reading in a GIOChannel



On Tue, 2007-05-29 at 22:42 +0100, Robert Pearce wrote:

> My understanding was that the Glib idle task checks the IO channel 
> status and calls the callback if it's ready. Since Glib is non-threaded, 
> this cannot happen during a previous execution of the callback. And 
> since it uses the channel's state rather than any edge events, no data 
> will be lost or ignored simply because the callback was running at the 
> time it arrived. Indeed this must be true if Glib is non-threaded, 
> because the data may arrive at any time and some huge Gtk re-draw may be 
> in progress when it happens. But that's only my understanding as a user 
> so I'd advise you all to ask one of the authors.

I am not one of the authors, but that is how it works (although on Unix
not using an idle task).  The GIOWatch/GSource object for a GIOChannel
watch uses poll() (on Unix) and if a watch is set on a GIOChannel object
and data arrives while the main loop is executing, or indeed while a
read of the GIOChannel object in the watch callback is taking place,
then when the current main loop iteration has finished the main loop
will be fired again and the data will be picked up on the next iteration
through the loop.  It would be a huge bug if after setting a watch on a
GIOChannel object, the watch permanently misses data arriving while the
main loop is doing other things, or indeed is doing a read of the same
GIOChannel object.

The normal way of dealing with the OP's situation is to set a watch on
the GIOChannel object, and then for the watch callback to do
non-blocking reads which loop until EAGAIN is received (equating to
g_io_channel_read_*() returning G_IO_STATUS_AGAIN).

According to the OP's original posting he has in the past made blocking
reads on C++ streams which rely on std::streambuf::is_avail() or its
equivalent in Java.  That is fairly hopeless as it only tells you what
is in the buffers, not what the system has available for reading.  It
therefore represents very old news - it tells you the minimum that can
be read without blocking (which could be 0), but certainly not the
maximum which can be read without blocking (which could be lots more).
In fact in C++ streambufs (I don't know about Java buffers but I imagine
the same applies) a stalemate can be reached, whereby because is_avail()
returns 0 no read is made, and because no read is made the buffers never
fill up.

On your threading point, glib is threaded in the sense that it is thread
safe and that you can have different GMainContext objects in different
threads.  So you could have a special thread with its own main loop
which only, for example, deals with reading from particular pipes or
sockets.  However, that is not relevant to the OP's enquiry (if reading
via a watch attached to that thread's main loop, he would still need to
do non-blocking reads in the way described above).

Chris





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