From: Bill Kelly Date: 2004-09-23T04:25:12+09:00 Subject: Re: TCP Socket read and write Hi Brian, From: "Brian Candler" > On Wed, Sep 22, 2004 at 03:50:53AM +0900, Bill Kelly wrote: > > Oh.. hehe... No, it's intended to be connected to a remote > > socket. (Or at least, to a socket whose other end is > > connected to a different process.) > > > > I suppose in practice it's a convenience mechanism. It lets > > my main thread blast an arbitrarily large chunk of data at > > the BufferedIO#send_nonblock without having to wait. The main > > thread can go about its business, knowing that data will be > > sent by BufferedIO to the remote host as fast as it can be. > > Oh I see now. > > Well, I can make my code have an API like yours, but it seems very unnatural > to me. For exmaple, #recv_nonblock always returns "" if no data is available > - but you cannot do a select() on a BufferedIO object, so you have to waste > time polling it. The data_ready_signal passed into BufferedIO provides a means to wait rather than poll. My application, which is currently structured around a select() dispatch, uses global-signal instead, as in effect a drop-in replacement for select(). So my main loop, instead of using select, like: nready = select([@tcp_clients], nil, nil, timeout) Has a semantically-similar, if you will, timed wait like: begin @global_signal.timed_wait(timeout) rescue Timeout::Error > My code fails your unit tests with some deadlock problem. I don't understand > what timed-wait is doing, so I can't really fix it. I've never found I've > had to use Thread.stop and the like; Ruby's primitives like Mutex, Queue, > SizedQueue, and Timeout always seem to do the job. I wasn't happy with how complex timed_wait was when I wrote it. It was the culmination of a week-long learning experience, bug hunt, and wild goose chase, coming to an understanding of why ruby's timeout is hazardous to my health. Timeout will interrupt your thread anywhere, even inside an ensure block. (This makes it difficult if not impossible to use a timeout block on code that internally uses ensure to release some critical resource.) It all started when I tried to do a timeout around a condition variable wait. My quest started here: Subject: How safe is 'timeout' ? http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/110306 And ended here with the timed_wait you see now: Subject: Re: Request For Comments: exception safe ConditionVariable#wait http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/110799 > I think what I'm saying is: there's a more natural way to do it in Ruby. Yes, from the complexity of some of the resultant code, I seem to be fighting the language to make this drop-in replacement for select-with-timeout. It seemed like a simple idea. I had a single-threaded app that uses select() with a timeout. I thought my life would be simpler if I could keep that structure, but just increase the buffer size to infinity on my IO objects behind the scenes. . . . . However, by this point, I could have long since rewritten the app to be totally multithreaded. ;-/ However - should you ever need a ConditionVariable#wait with a timeout--as my app does as it's *currently* structured--I haven't yet found a simpler way to do it safely than that ugly timed_wait. > > I have always had a love-hate relationship > > with both multithreading, and single-threaded select() dispatch > > loops. > > For me, it's now a love-love relationship. I've seen programs which consist > of pages and pages of C, implementing select() across arrays of > filedescriptors and an array of state machines for each socket; then I've > rewritten it into a couple of screens of Ruby using Threads. The Ruby code > works far better, as it's less buggy :-) I'm contemplating going ahead and thorougly restructuring my app, around ruby threads and primitives like Queue, and see how it turns out. I will avoid Timeout, however, unless I'm certain the code within the timeout block makes no use of ensure or otherwise has no need to manage any critical resources or maintain class invariants, etc... Thanks again for your thoughts, Regards, Bill