Project

General

Profile

Feature #3187 ยป fiber_stacksize.patch

nagachika (Tomoyuki Chikanaga), 10/19/2011 11:26 PM

View differences:

cont.c
116 116
static VALUE rb_cContinuation;
117 117
static VALUE rb_cFiber;
118 118
static VALUE rb_eFiberError;
119
static ID id_default_vm_stacksize;
120
static ID id_vm_stacksize;
119 121

  
120 122
#define GetContPtr(obj, ptr)  \
121 123
    TypedData_Get_Struct((obj), rb_context_t, &cont_data_type, (ptr))
......
1016 1018
}
1017 1019

  
1018 1020
static VALUE
1019
fiber_init(VALUE fibval, VALUE proc)
1021
fiber_init(VALUE fibval, VALUE proc, VALUE vm_stacksize)
1020 1022
{
1021 1023
    rb_fiber_t *fib = fiber_t_alloc(fibval);
1022 1024
    rb_context_t *cont = &fib->cont;
......
1030 1032

  
1031 1033
    fiber_link_join(fib);
1032 1034

  
1033
    th->stack_size = FIBER_VM_STACK_SIZE;
1035
    th->stack_size = NUM2ULONG(vm_stacksize);
1034 1036
    th->stack = ALLOC_N(VALUE, th->stack_size);
1035 1037

  
1036 1038
    th->cfp = (void *)(th->stack + th->stack_size);
......
1060 1062
}
1061 1063

  
1062 1064
/* :nodoc: */
1065
static VALUE rb_fiber_s_get_default_vm_stacksize(VALUE);
1066

  
1063 1067
static VALUE
1064
rb_fiber_init(VALUE fibval)
1068
rb_fiber_init(int argc, VALUE *argv, VALUE fibval)
1065 1069
{
1066
    return fiber_init(fibval, rb_block_proc());
1070
    VALUE opt;
1071
    VALUE stacksize;
1072

  
1073
    rb_scan_args(argc, argv, "0:", &opt);
1074
    if (NIL_P(opt) || NIL_P(rb_hash_aref(opt, ID2SYM(id_vm_stacksize))))
1075
	stacksize = rb_fiber_s_get_default_vm_stacksize(rb_obj_class(fibval));
1076
    else
1077
	stacksize = rb_to_int(rb_hash_aref(opt, ID2SYM(id_vm_stacksize)));
1078
    if (NUM2ULONG(stacksize) < (unsigned long)FIBER_VM_STACK_SIZE)
1079
	rb_raise(rb_eArgError,
1080
		 "Fiber vm stacksize must equal or bigger than %d",
1081
		 FIBER_VM_STACK_SIZE);
1082

  
1083
    return fiber_init(fibval, rb_block_proc(), stacksize);
1067 1084
}
1068 1085

  
1069 1086
VALUE
1070 1087
rb_fiber_new(VALUE (*func)(ANYARGS), VALUE obj)
1071 1088
{
1072
    return fiber_init(fiber_alloc(rb_cFiber), rb_proc_new(func, obj));
1089
    return fiber_init(fiber_alloc(rb_cFiber), rb_proc_new(func, obj),
1090
		      rb_fiber_s_get_default_vm_stacksize(rb_cFiber));
1073 1091
}
1074 1092

  
1075 1093
static VALUE
......
1396 1414

  
1397 1415
/*
1398 1416
 *  call-seq:
1417
 *    fiber.vm_stacksize() -> integer
1418
 *
1419
 *  Returns VM stack size of the fiber.
1420
 */
1421
static VALUE
1422
rb_fiber_vm_stacksize(VALUE fibval)
1423
{
1424
    rb_fiber_t *fib;
1425
    GetFiberPtr(fibval, fib);
1426
    return ULONG2NUM(fib->cont.saved_thread.stack_size);
1427
}
1428

  
1429
/*
1430
 *  call-seq:
1399 1431
 *     Fiber.yield(args, ...) -> obj
1400 1432
 *
1401 1433
 *  Yields control back to the context that resumed the fiber, passing
......
1424 1456
    return rb_fiber_current();
1425 1457
}
1426 1458

  
1459
/*
1460
 *  call-seq:
1461
 *    Fiber.default_vm_stacksize() -> integer
1462
 *
1463
 *  Returns the default VM stack size. Note that this is a maximum number of
1464
 *  object in VM stack, not a size in byte.
1465
 */
1466
static VALUE
1467
rb_fiber_s_get_default_vm_stacksize(VALUE klass)
1468
{
1469
	return rb_ivar_get(klass, id_default_vm_stacksize);
1470
}
1427 1471

  
1472
/*
1473
 *  call-seq:
1474
 *    Fiber.default_vm_stacksize = num -> integer
1475
 *
1476
 *  Sets the default VM stack size.
1477
 *  Returns +num+.
1478
 *  Raises TypeError if +num+ is not Numeric and
1479
 *  raises ArgumentError if num is less than FIBER_VM_STACK_SIZE.
1480
 */
1481
static VALUE
1482
rb_fiber_s_set_default_vm_stacksize(VALUE klass, VALUE num)
1483
{
1484
	num = rb_to_int(num);
1485
	if (NUM2ULONG(num) < (unsigned long)FIBER_VM_STACK_SIZE)
1486
	    rb_raise(rb_eArgError,
1487
		     "Fiber default_vm_stacksize must equal or bigger than %d",
1488
		     FIBER_VM_STACK_SIZE);
1489
	rb_ivar_set(klass, id_default_vm_stacksize, num);
1490
	return num;
1491
}
1428 1492

  
1429 1493
/*
1430 1494
 *  Document-class: FiberError
......
1455 1519
    SET_MACHINE_STACK_END(&th->machine_stack_end);
1456 1520
#endif
1457 1521

  
1522
    id_default_vm_stacksize = rb_intern("default_vm_stacksize");
1523
    id_vm_stacksize = rb_intern("vm_stacksize");
1524

  
1458 1525
    rb_cFiber = rb_define_class("Fiber", rb_cObject);
1459 1526
    rb_define_alloc_func(rb_cFiber, fiber_alloc);
1460 1527
    rb_eFiberError = rb_define_class("FiberError", rb_eStandardError);
1528
    rb_ivar_set(rb_cFiber, id_default_vm_stacksize,
1529
		INT2NUM(FIBER_VM_STACK_SIZE));
1530
    rb_define_singleton_method(rb_cFiber, "default_vm_stacksize",
1531
			       rb_fiber_s_get_default_vm_stacksize, 0);
1532
    rb_define_singleton_method(rb_cFiber, "default_vm_stacksize=",
1533
			       rb_fiber_s_set_default_vm_stacksize, 1);
1461 1534
    rb_define_singleton_method(rb_cFiber, "yield", rb_fiber_s_yield, -1);
1462
    rb_define_method(rb_cFiber, "initialize", rb_fiber_init, 0);
1535
    rb_define_method(rb_cFiber, "initialize", rb_fiber_init, -1);
1463 1536
    rb_define_method(rb_cFiber, "resume", rb_fiber_m_resume, -1);
1537
    rb_define_method(rb_cFiber, "vm_stacksize", rb_fiber_vm_stacksize, 0);
1464 1538
}
1465 1539

  
1466 1540
#if defined __GNUC__ && __GNUC__ >= 4
test/ruby/test_fiber.rb
220 220
    end
221 221
    assert_equal("Can't call on top of Fiber or Thread", error.message, bug5083)
222 222
  end
223

  
224
  def test_default_vm_stacksize
225
    begin
226
      default_vm_stacksize = Fiber.default_vm_stacksize
227
      assert_equal(4*1024, default_vm_stacksize)
228
      Fiber.default_vm_stacksize = 8 * 1024
229
      assert_equal(8*1024, Fiber.default_vm_stacksize)
230
      assert_raise(TypeError) do
231
        Fiber.default_vm_stacksize = Object.new
232
      end
233
      assert_raise(ArgumentError) do
234
        Fiber.default_vm_stacksize = 0
235
      end
236
    ensure
237
      if default_vm_stacksize
238
        Fiber.default_vm_stacksize = default_vm_stacksize
239
      end
240
    end
241
  end
242

  
243
  def test_vm_stacksize
244
    fib = Fiber.new { }
245
    assert_equal(Fiber.default_vm_stacksize, fib.vm_stacksize)
246
    fib = Fiber.new(:vm_stacksize => 8*1024) {}
247
    assert_equal(8*1024, fib.vm_stacksize)
248
    assert_raise(TypeError) do
249
      Fiber.new(:vm_stacksize => Object.new) {}
250
    end
251
    assert_raise(ArgumentError) do
252
      Fiber.new(:vm_stacksize => 2 * 1024) {}
253
    end
254
  end
223 255
end
224 256