Project

General

Profile

Feature #10344 » 0001-Implement-Fiber-raise.patch

nome (Knut Franke), 10/09/2014 12:19 AM

View differences:

cont.c
make_passing_arg(int argc, const VALUE *argv)
{
switch (argc) {
case -1:
return argv[0];
case 0:
return Qnil;
case 1:
......
/*
* call-seq:
* fiber.raise(string) -> obj
* fiber.raise(exception [, string [, array]]) -> obj
*
* Assuming that <code>resume</code> was called before, raises an exception in
* the fiber at the point at which the last <code>Fiber.yield</code> was
* called. If the <code>Fiber.yield</code> occurs within a
* <code>begin...end</code> block with a +rescue+ clause matching the
* exception being raised, <code>fiber.raise</code> evaluates to the arguments
* passed to the next <code>Fiber.yield</code> statement inside the fiber's
* block or to the block value if it runs to completion without any
* <code>Fiber.yield</code>. Otherwise, the exception is propagated to the
* caller.
*
* If the fiber either has never been resumed or is dead, raises FiberError.
*
* 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.
*/
static VALUE
rb_fiber_raise(int argc, VALUE *argv, VALUE fibval)
{
VALUE exc;
rb_fiber_t *fib;
GetFiberPtr(fibval, fib);
switch(fib->status) {
case CREATED:
rb_raise(rb_eFiberError, "Cannot raise exception in an unborn fiber."
" You need to resume first.");
case RUNNING:
exc = rb_make_exception(argc, argv);
return rb_fiber_resume(fibval, -1, &exc);
case TERMINATED:
rb_raise(rb_eFiberError, "Cannot raise exception in a dead fiber.");
}
return Qundef;
}
/*
* call-seq:
* fiber.transfer(args, ...) -> obj
*
* Transfer control to another fiber, resuming it from where it last
......
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);
}
RUBY_SYMBOL_EXPORT_BEGIN
test/ruby/test_fiber.rb
}
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
......
}
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
(1-1/3)