зеркало из https://github.com/github/ruby.git
Implement Fiber#raise. Fixes #10344.
This allows raising exceptions in another fiber, similarly to Thread#raise. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66610 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
Родитель
b0d24baf8a
Коммит
5fb9d1e11f
29
cont.c
29
cont.c
|
@ -1228,6 +1228,8 @@ static VALUE
|
|||
make_passing_arg(int argc, const VALUE *argv)
|
||||
{
|
||||
switch (argc) {
|
||||
case -1:
|
||||
return argv[0];
|
||||
case 0:
|
||||
return Qnil;
|
||||
case 1:
|
||||
|
@ -1954,6 +1956,32 @@ rb_fiber_m_resume(int argc, VALUE *argv, VALUE fib)
|
|||
return rb_fiber_resume(fib, argc, argv);
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* fiber.raise -> obj
|
||||
* fiber.raise(string) -> obj
|
||||
* fiber.raise(exception [, string [, array]]) -> obj
|
||||
*
|
||||
* Raises an exception in the fiber at the point at which the last
|
||||
* <code>Fiber.yield</code> was called, or at the start if neither +resume+
|
||||
* nor +raise+ were called before.
|
||||
*
|
||||
* With no arguments, raises a +RuntimeError+. With a single +String+
|
||||
* argument, raises a +RuntimeError+ with the string as a message. Otherwise,
|
||||
* the first parameter should be the name of an +Exception+ class (or an
|
||||
* object that returns an +Exception+ object when sent an +exception+
|
||||
* message). The optional second parameter sets the message associated with
|
||||
* the exception, and the third parameter is an array of callback information.
|
||||
* Exceptions are caught by the +rescue+ clause of <code>begin...end</code>
|
||||
* blocks.
|
||||
*/
|
||||
static VALUE
|
||||
rb_fiber_raise(int argc, VALUE *argv, VALUE fib)
|
||||
{
|
||||
VALUE exc = rb_make_exception(argc, argv);
|
||||
return rb_fiber_resume(fib, -1, &exc);
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* fiber.transfer(args, ...) -> obj
|
||||
|
@ -2112,6 +2140,7 @@ Init_Cont(void)
|
|||
rb_define_singleton_method(rb_cFiber, "yield", rb_fiber_s_yield, -1);
|
||||
rb_define_method(rb_cFiber, "initialize", rb_fiber_init, 0);
|
||||
rb_define_method(rb_cFiber, "resume", rb_fiber_m_resume, -1);
|
||||
rb_define_method(rb_cFiber, "raise", rb_fiber_raise, -1);
|
||||
rb_define_method(rb_cFiber, "to_s", fiber_to_s, 0);
|
||||
rb_define_alias(rb_cFiber, "inspect", "to_s");
|
||||
}
|
||||
|
|
|
@ -109,6 +109,15 @@ class TestFiber < Test::Unit::TestCase
|
|||
}
|
||||
fib.resume
|
||||
}
|
||||
assert_raise(FiberError){
|
||||
fib = Fiber.new{}
|
||||
fib.raise "raise in unborn fiber"
|
||||
}
|
||||
assert_raise(FiberError){
|
||||
fib = Fiber.new{}
|
||||
fib.resume
|
||||
fib.raise "raise in dead fiber"
|
||||
}
|
||||
end
|
||||
|
||||
def test_return
|
||||
|
@ -127,6 +136,37 @@ class TestFiber < Test::Unit::TestCase
|
|||
}
|
||||
end
|
||||
|
||||
def test_raise
|
||||
assert_raise(ZeroDivisionError){
|
||||
Fiber.new do
|
||||
1/0
|
||||
end.resume
|
||||
}
|
||||
assert_raise(RuntimeError){
|
||||
fib = Fiber.new{ Fiber.yield }
|
||||
fib.raise "raise and propagate"
|
||||
}
|
||||
assert_nothing_raised{
|
||||
fib = Fiber.new do
|
||||
begin
|
||||
Fiber.yield
|
||||
rescue
|
||||
end
|
||||
end
|
||||
fib.resume
|
||||
fib.raise "rescue in fiber"
|
||||
}
|
||||
fib = Fiber.new do
|
||||
begin
|
||||
Fiber.yield
|
||||
rescue
|
||||
Fiber.yield :ok
|
||||
end
|
||||
end
|
||||
fib.resume
|
||||
assert_equal(:ok, fib.raise)
|
||||
end
|
||||
|
||||
def test_transfer
|
||||
ary = []
|
||||
f2 = nil
|
||||
|
|
Загрузка…
Ссылка в новой задаче