Project

General

Profile

Feature #10344 ยป 0001-Implement-Fiber-raise.patch

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

View differences:

cont.c
941 941
make_passing_arg(int argc, const VALUE *argv)
942 942
{
943 943
    switch (argc) {
944
      case -1:
945
	return argv[0];
944 946
      case 0:
945 947
	return Qnil;
946 948
      case 1:
......
1559 1561

  
1560 1562
/*
1561 1563
 *  call-seq:
1564
 *     fiber.raise(string)                         -> obj
1565
 *     fiber.raise(exception [, string [, array]]) -> obj
1566
 *
1567
 *  Assuming that <code>resume</code> was called before, raises an exception in
1568
 *  the fiber at the point at which the last <code>Fiber.yield</code> was
1569
 *  called. If the <code>Fiber.yield</code> occurs within a
1570
 *  <code>begin...end</code> block with a +rescue+ clause matching the
1571
 *  exception being raised, <code>fiber.raise</code> evaluates to the arguments
1572
 *  passed to the next <code>Fiber.yield</code> statement inside the fiber's
1573
 *  block or to the block value if it runs to completion without any
1574
 *  <code>Fiber.yield</code>. Otherwise, the exception is propagated to the
1575
 *  caller.
1576
 *
1577
 *  If the fiber either has never been resumed or is dead, raises FiberError.
1578
 *
1579
 *  With a single +String+ argument, raises a +RuntimeError+ with the string as
1580
 *  a message.  Otherwise, the first parameter should be the name of an
1581
 *  +Exception+ class (or an object that returns an +Exception+ object when
1582
 *  sent an +exception+ message). The optional second parameter sets the
1583
 *  message associated with the exception, and the third parameter is an array
1584
 *  of callback information.
1585
 */
1586
static VALUE
1587
rb_fiber_raise(int argc, VALUE *argv, VALUE fibval)
1588
{
1589
    VALUE exc;
1590
    rb_fiber_t *fib;
1591
    GetFiberPtr(fibval, fib);
1592
    switch(fib->status) {
1593
	case CREATED:
1594
	    rb_raise(rb_eFiberError, "Cannot raise exception in an unborn fiber."
1595
		    " You need to resume first.");
1596
	case RUNNING:
1597
	    exc = rb_make_exception(argc, argv);
1598
	    return rb_fiber_resume(fibval, -1, &exc);
1599
	case TERMINATED:
1600
	    rb_raise(rb_eFiberError, "Cannot raise exception in a dead fiber.");
1601
    }
1602
    return Qundef;
1603
}
1604

  
1605
/*
1606
 *  call-seq:
1562 1607
 *     fiber.transfer(args, ...) -> obj
1563 1608
 *
1564 1609
 *  Transfer control to another fiber, resuming it from where it last
......
1678 1723
    rb_define_singleton_method(rb_cFiber, "yield", rb_fiber_s_yield, -1);
1679 1724
    rb_define_method(rb_cFiber, "initialize", rb_fiber_init, 0);
1680 1725
    rb_define_method(rb_cFiber, "resume", rb_fiber_m_resume, -1);
1726
    rb_define_method(rb_cFiber, "raise", rb_fiber_raise, -1);
1681 1727
}
1682 1728

  
1683 1729
RUBY_SYMBOL_EXPORT_BEGIN
test/ruby/test_fiber.rb
107 107
      }
108 108
      fib.resume
109 109
    }
110
    assert_raise(FiberError){
111
      fib = Fiber.new{}
112
      fib.raise "raise in unborn fiber"
113
    }
114
    assert_raise(FiberError){
115
      fib = Fiber.new{}
116
      fib.resume
117
      fib.raise "raise in dead fiber"
118
    }
110 119
  end
111 120

  
112 121
  def test_return
......
125 134
    }
126 135
  end
127 136

  
137
  def test_raise
138
    assert_raise(ZeroDivisionError){
139
      Fiber.new do
140
        1/0
141
      end.resume
142
    }
143
    assert_raise(RuntimeError){
144
      fib = Fiber.new{ Fiber.yield }
145
      fib.raise "raise and propagate"
146
    }
147
    assert_nothing_raised{
148
      fib = Fiber.new do
149
        begin
150
          Fiber.yield
151
        rescue
152
        end
153
      end
154
      fib.resume
155
      fib.raise "rescue in fiber"
156
    }
157
    fib = Fiber.new do
158
      begin
159
        Fiber.yield
160
      rescue
161
        Fiber.yield :ok
162
      end
163
    end
164
    fib.resume
165
    assert_equal(:ok, fib.raise)
166
  end
167

  
128 168
  def test_transfer
129 169
    ary = []
130 170
    f2 = nil
131
-