aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorakr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2008-12-22 12:27:26 +0000
committerakr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2008-12-22 12:27:26 +0000
commit3a7daf882bf737c2e9a6c7a9aece2424cb3f4547 (patch)
tree16383b4b77598d0f449a9617e877ceb90a8e7e74
parentc8cbfe7deba037b72e2a3c8f7dd604731e43de55 (diff)
downloadruby-3a7daf882bf737c2e9a6c7a9aece2424cb3f4547.tar.gz
* io.c (rb_io_s_pipe): IO.pipe can take a block.
(pipe_close): new function. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@20916 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--ChangeLog5
-rw-r--r--NEWS3
-rw-r--r--io.c36
-rw-r--r--test/ruby/test_io.rb28
4 files changed, 69 insertions, 3 deletions
diff --git a/ChangeLog b/ChangeLog
index 905be7f93b..14e1de5e3f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+Mon Dec 22 21:26:12 2008 Tanaka Akira <akr@fsij.org>
+
+ * io.c (rb_io_s_pipe): IO.pipe can take a block.
+ (pipe_close): new function.
+
Mon Dec 22 21:08:54 2008 Tanaka Akira <akr@fsij.org>
* lib/test/unit/assertions.rb (assert_nothing_raised): increment
diff --git a/NEWS b/NEWS
index 5a1e08d011..263f87d472 100644
--- a/NEWS
+++ b/NEWS
@@ -13,6 +13,9 @@ with all sufficient information, see the ChangeLog file.
* builtin classes
+ * IO
+ * IO.pipe takes a block.
+
* Enumerator#rewind
Now calls the "rewind" method of the enclosed object if defined.
diff --git a/io.c b/io.c
index f5efd3719b..888fee9175 100644
--- a/io.c
+++ b/io.c
@@ -6906,6 +6906,21 @@ io_encoding_set(rb_io_t *fptr, VALUE v1, VALUE v2, VALUE opt)
}
+static
+VALUE pipe_close(VALUE args)
+{
+ VALUE *rw = (VALUE*)args;
+ VALUE io;
+ int i;
+
+ for (i = 0; i < 2; i++) {
+ io = rw[i];
+ if (!rb_io_closed(io))
+ rb_io_close(io);
+ }
+ return Qnil;
+}
+
/*
* call-seq:
* IO.pipe -> [read_io, write_io]
@@ -6913,10 +6928,17 @@ io_encoding_set(rb_io_t *fptr, VALUE v1, VALUE v2, VALUE opt)
* IO.pipe("ext_enc:int_enc" [, opt]) -> [read_io, write_io]
* IO.pipe(ext_enc, int_enc [, opt]) -> [read_io, write_io]
*
+ * IO.pipe(...) {|read_io, write_io| ... }
+ *
* Creates a pair of pipe endpoints (connected to each other) and
* returns them as a two-element array of <code>IO</code> objects:
- * <code>[</code> <i>read_io</i>, <i>write_io</i> <code>]</code>. Not
- * available on all platforms.
+ * <code>[</code> <i>read_io</i>, <i>write_io</i> <code>]</code>.
+ *
+ * If a block is given, the block is called and
+ * returns the value of the block.
+ * <i>read_io</i> and <i>write_io</i> are sent to the block as arguments.
+ *
+ * Not available on all platforms.
*
* If an encoding (encoding name or encoding object) is specified as an optional argument,
* read string from pipe is tagged with the encoding specified.
@@ -6965,6 +6987,8 @@ rb_io_s_pipe(int argc, VALUE *argv, VALUE klass)
VALUE opt;
rb_io_t *fptr, *fptr2;
int fmode = 0;
+ VALUE ret;
+ VALUE rw[2];
opt = pop_last_hash(&argc, argv);
rb_scan_args(argc, argv, "02", &v1, &v2);
@@ -6997,7 +7021,13 @@ rb_io_s_pipe(int argc, VALUE *argv, VALUE klass)
fptr->mode |= fmode;
fptr2->mode |= fmode;
- return rb_assoc_new(r, w);
+ ret = rb_assoc_new(r, w);
+ rw[0] = r;
+ rw[1] = w;
+ if (rb_block_given_p()) {
+ return rb_ensure(rb_yield, ret, pipe_close, (VALUE)rw);
+ }
+ return ret;
}
struct foreach_arg {
diff --git a/test/ruby/test_io.rb b/test/ruby/test_io.rb
index 78cb425ed1..d00c0a3f7c 100644
--- a/test/ruby/test_io.rb
+++ b/test/ruby/test_io.rb
@@ -22,6 +22,34 @@ class TestIO < Test::Unit::TestCase
IO.instance_methods.index(:"nonblock=")
end
+ def test_pipe
+ r, w = IO.pipe
+ assert_instance_of(IO, r)
+ assert_instance_of(IO, w)
+ w.print "abc"
+ w.close
+ assert_equal("abc", r.read)
+ r.close
+ end
+
+ def test_pipe_block
+ x = nil
+ ret = IO.pipe {|r, w|
+ x = [r,w]
+ assert_instance_of(IO, r)
+ assert_instance_of(IO, w)
+ w.print "abc"
+ w.close
+ assert_equal("abc", r.read)
+ assert(!r.closed?)
+ assert(w.closed?)
+ :foooo
+ }
+ assert_equal(:foooo, ret)
+ assert(x[0].closed?)
+ assert(x[1].closed?)
+ end
+
def test_gets_rs
# default_rs
r, w = IO.pipe