From: Yehuda Katz Date: 2011-08-02T08:19:37+09:00 Subject: [ruby-core:38673] Re: [Ruby 1.9 - Bug #5138] Add nonblocking IO that does not use exceptions for EOF and EWOULDBLOCK --20cf3079b85a04ff5104a979ddd5 Content-Type: text/plain; charset=ISO-8859-1 In practice, it is not more verbose. Here's some example code from net/protocol, and once try_read_nonblock is used. Existing code: def rbuf_fill begin @rbuf << @io.read_nonblock(BUFSIZE) rescue IO::WaitReadable return retry if IO.select([@io], nil, nil, @read_timeout) raise Timeout::Error rescue IO::WaitWritable # OpenSSL::Buffering#read_nonblock may fail with IO::WaitWritable. # http://www.openssl.org/support/faq.html#PROG10 return retry if IO.select(nil, [@io], nil, @read_timeout) raise Timeout::Error end end With try_read_nonblock: def rbuf_fill case value = @io.try_read_nonblock(BUFSIZE) when :read_would_block return rbuf_fill if IO.select([@io], nil, nil, @read_timeout) raise Timeout::Error when :write_would_block return rbuf_fill if IO.select(nil, [@io], nil, @read_timeout) raise Timeout::Error when String @rbuf << value end end *As you can see, the control flow logic is almost identical, but we use Symbols instead of exceptions to manage the flow.* Yehuda Katz Chief Technologist | Strobe (ph) 718.877.1325 On Mon, Aug 1, 2011 at 3:49 PM, Shyouhei Urabe wrote: > > Issue #5138 has been updated by Shyouhei Urabe. > > > Instead of avoiding exceptions I would like to suggest making exceptions > lightweight. > > "Check those return values every time you call this function" is nothing > different from C. I would write my program totally in C if I have to do > that way. > ---------------------------------------- > Bug #5138: Add nonblocking IO that does not use exceptions for EOF and > EWOULDBLOCK > http://redmine.ruby-lang.org/issues/5138 > > Author: Yehuda Katz > Status: Open > Priority: Normal > Assignee: Yukihiro Matsumoto > Category: core > Target version: 1.9.4 > ruby -v: ruby 1.9.4dev (2011-07-31 trunk 32788) [x86_64-darwin11.0.0] > > > The current Ruby I/O classes have non-blocking methods (read_nonblock and > write_nonblock). These methods will never block, and if they would block, > they raise an exception instead (IO::WaitReadable or IO::WaitWritable). In > addition, if the IO is at EOF, they raise an EOFError. > > These exceptions are raised repeatedly in virtually every use of the > non-blocking methods. This patch adds a pair of methods (try_read_nonblock > and try_write_nonblock) that have the same semantics as the existing > methods, but they return Symbols instead of raising exceptions for these > routine cases: > > * :read_would_block > * :write_would_block > * :eof > > The patch contains updates for IO, StringIO, and OpenSSL. The updates are > fully documented and tested. > > > -- > http://redmine.ruby-lang.org > > --20cf3079b85a04ff5104a979ddd5 Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable In practice, it is not more verbose. Here's some example code from net/= protocol, and once try_read_nonblock is used.

Existing c= ode:


def rbuf_fill
=A0=A0begin
=A0=A0=A0= =A0@rbuf << @io.read_nonblock(BUFSIZE)
=A0=A0rescue IO::WaitReadable
=A0=A0=A0= =A0re= turn retry if IO.select([@io], nil, , @= read_timeout)
=A0=A0=A0= =A0ra= ise Timeout::Error
=A0=A0rescue IO::WaitWritable
=A0=A0=A0= =A0# OpenSSL::Buffering#read_nonblock may fail with= IO::WaitWritable.
=A0=A0=A0= =A0# http://www.openssl.org/support/faq.html#PROG10
=A0=A0=A0= =A0re= turn retry if IO.select(nil, [<= /span>@io], , @= read_timeout)
=A0=A0=A0= =A0ra= ise Timeout::Error
=A0=A0end
end

With try_read_nonblock:

def rbuf_fill
=A0=A0case value =3D = @io.try_read_no= nblock(B= UFSIZE)
=A0=A0when :read_would_block
=A0=A0=A0= =A0re= turn rbuf_fill = if IO.= select([= ], = nil<= /span>, nil, @read_timeout)
=A0=A0=A0= =A0ra= ise Timeout::Error
=A0=A0when :write_would_block
=A0=A0=A0= =A0re= turn rbuf_fill = if IO.= select(nil, [@io]= , nil, @read_timeout)
=A0=A0=A0= =A0ra= ise Timeout::Error
=A0=A0when String
=A0=A0=A0= =A0@rbuf << value
=A0=A0end
end
=
As you can see, the control flow logic is almost identical,= but we use Symbols instead of exceptions to manage the flow.


Yehuda Katz
Chi= ef Technologist | Strobe
(ph) 718.877.1325


On Mon, Aug 1, 2011 at 3:49 PM, Shyouhei= Urabe <shyo= uhei@ruby-lang.org> wrote:

Issue #5138 has been updated by Shyouhei Urabe.


Instead of avoiding exceptions I would like to suggest making exceptions li= ghtweight.

"Check those return values every time you call this function" is = nothing different from C. =A0I would write my program totally in C if I hav= e to do that way.
----------------------------------------<= br> Bug #5138: Add nonblocking IO that does not use exceptions for EOF and EWOU= LDBLOCK
http= ://redmine.ruby-lang.org/issues/5138

Author: Yehuda Katz
Status: Open
Priority: Normal
Assignee: Yukihiro Matsumoto
Category: core
Target version: 1.9.4
ruby -v: ruby 1.9.4dev (2011-07-31 trunk 32788) [x86_64-darwin11.0.0]


The current Ruby I/O classes have non-blocking methods (read_nonblock and w= rite_nonblock). These methods will never block, and if they would block, th= ey raise an exception instead (IO::WaitReadable or IO::WaitWritable). In ad= dition, if the IO is at EOF, they raise an EOFError.

These exceptions are raised repeatedly in virtually every use of the non-bl= ocking methods. This patch adds a pair of methods (try_read_nonblock and tr= y_write_nonblock) that have the same semantics as the existing methods, but= they return Symbols instead of raising exceptions for these routine cases:=

* :read_would_block
* :write_would_block
* :eof

The patch contains updates for IO, StringIO, and OpenSSL. The updates are f= ully documented and tested.


--
http://redmine.r= uby-lang.org


--20cf3079b85a04ff5104a979ddd5--