On Tue, 2003-03-18 at 16:58, Brian Candler wrote:
> On Wed, Mar 19, 2003 at 07:03:09AM +0900, Tom Felker wrote:
> > What I need is to get the real handle to the socket.  (Or any other way
> > to set a socket nonblocking in Windows.)
> 
> There is an alternative way in Ruby: threads.
> 
> If you start a thread, and then read from a socket (say), it doesn't matter
> if it's a "blocking" read; other threads can continue to run. The Ruby
> interpreter hides all the details of how it achieves that.

Wow.  My (flawed) understanding of how green threads work, in
combination with a misreading of the introduction to the Threads chapter
of the Programmer's guide, made me ignore this.  But after a quick test,
it works, even with GTK.  Cool!

> > Also, a way to make TCPSocket.new not block would be nice.  I'm trying
> > to make a chat program, and it needs to stay responsive, so it uses the
> > GUI toolkit's functions to register a callback when the socket is
> > selected for.
> 
> Threads sound like the right way for this. You may require a little care
> with concurrency issues, but that's all. At best: the chat receiver 'owns'
> one Window, and can put messages in their asynchronously. At worst: you need
> a mutex so that only one thread is making a GUI API call at any time. It
> depends on how thread-safe your GUI toolkit is.
> 
> You should certainly be able to get the responsiveness you're after, and the
> code will probably end up simpler.
> 
> Another approach (also based on threads) would be to have your message
> receiver put whole received messages into a queue. It just needs to sit in a
> loop of (read whole message - write it to queue). The queue add and remove
> operations need to be thread-safe, but then your main loop can simply check
> for whether there are messages in there or not, just as if it were doing a
> non-blocking read, but without the complications of having to deal with a
> read() which returns half a message.

Using a queue and only one thread for the GUI sounds best, the only
question is how that thread gets out of Gtk.main when the queue is added
to.  Using a timeout should work, but it's hackish and a trade off
between CPU and latency.

Putting a mutex around all the API calls would be fine as long as it's
OK to change widgets while the GUI thread is sleeping in Gtk.main,
because the mutex would have to be dropped when the GUI is asleep
there.  I'm not sure (but maybe it is) if that's safe in GTK.  Gtk.main
still needs to be woken up eventually, because it only redraws the
screen in idle functions, which won't be called again until a message is
received.

I eventually plan to write other UIs, in FOX, TK, or even text-based.  I
think my design is flexible enough that this can be done in different
ways depending on the needs of the toolkit, with the network code
entirely platform-independent.

> Regards,
> 
> Brian.

Thanks for removing my mental block about threads.
-- 
Tom Felker

"Proprietary standard" is an oxymoron.