Feature #3187 ยป fiber_stacksize.patch
| cont.c | ||
|---|---|---|
|
static VALUE rb_cContinuation;
|
||
|
static VALUE rb_cFiber;
|
||
|
static VALUE rb_eFiberError;
|
||
|
static ID id_default_vm_stacksize;
|
||
|
static ID id_vm_stacksize;
|
||
|
#define GetContPtr(obj, ptr) \
|
||
|
TypedData_Get_Struct((obj), rb_context_t, &cont_data_type, (ptr))
|
||
| ... | ... | |
|
}
|
||
|
static VALUE
|
||
|
fiber_init(VALUE fibval, VALUE proc)
|
||
|
fiber_init(VALUE fibval, VALUE proc, VALUE vm_stacksize)
|
||
|
{
|
||
|
rb_fiber_t *fib = fiber_t_alloc(fibval);
|
||
|
rb_context_t *cont = &fib->cont;
|
||
| ... | ... | |
|
fiber_link_join(fib);
|
||
|
th->stack_size = FIBER_VM_STACK_SIZE;
|
||
|
th->stack_size = NUM2ULONG(vm_stacksize);
|
||
|
th->stack = ALLOC_N(VALUE, th->stack_size);
|
||
|
th->cfp = (void *)(th->stack + th->stack_size);
|
||
| ... | ... | |
|
}
|
||
|
/* :nodoc: */
|
||
|
static VALUE rb_fiber_s_get_default_vm_stacksize(VALUE);
|
||
|
static VALUE
|
||
|
rb_fiber_init(VALUE fibval)
|
||
|
rb_fiber_init(int argc, VALUE *argv, VALUE fibval)
|
||
|
{
|
||
|
return fiber_init(fibval, rb_block_proc());
|
||
|
VALUE opt;
|
||
|
VALUE stacksize;
|
||
|
rb_scan_args(argc, argv, "0:", &opt);
|
||
|
if (NIL_P(opt) || NIL_P(rb_hash_aref(opt, ID2SYM(id_vm_stacksize))))
|
||
|
stacksize = rb_fiber_s_get_default_vm_stacksize(rb_obj_class(fibval));
|
||
|
else
|
||
|
stacksize = rb_to_int(rb_hash_aref(opt, ID2SYM(id_vm_stacksize)));
|
||
|
if (NUM2ULONG(stacksize) < (unsigned long)FIBER_VM_STACK_SIZE)
|
||
|
rb_raise(rb_eArgError,
|
||
|
"Fiber vm stacksize must equal or bigger than %d",
|
||
|
FIBER_VM_STACK_SIZE);
|
||
|
return fiber_init(fibval, rb_block_proc(), stacksize);
|
||
|
}
|
||
|
VALUE
|
||
|
rb_fiber_new(VALUE (*func)(ANYARGS), VALUE obj)
|
||
|
{
|
||
|
return fiber_init(fiber_alloc(rb_cFiber), rb_proc_new(func, obj));
|
||
|
return fiber_init(fiber_alloc(rb_cFiber), rb_proc_new(func, obj),
|
||
|
rb_fiber_s_get_default_vm_stacksize(rb_cFiber));
|
||
|
}
|
||
|
static VALUE
|
||
| ... | ... | |
|
/*
|
||
|
* call-seq:
|
||
|
* fiber.vm_stacksize() -> integer
|
||
|
*
|
||
|
* Returns VM stack size of the fiber.
|
||
|
*/
|
||
|
static VALUE
|
||
|
rb_fiber_vm_stacksize(VALUE fibval)
|
||
|
{
|
||
|
rb_fiber_t *fib;
|
||
|
GetFiberPtr(fibval, fib);
|
||
|
return ULONG2NUM(fib->cont.saved_thread.stack_size);
|
||
|
}
|
||
|
/*
|
||
|
* call-seq:
|
||
|
* Fiber.yield(args, ...) -> obj
|
||
|
*
|
||
|
* Yields control back to the context that resumed the fiber, passing
|
||
| ... | ... | |
|
return rb_fiber_current();
|
||
|
}
|
||
|
/*
|
||
|
* call-seq:
|
||
|
* Fiber.default_vm_stacksize() -> integer
|
||
|
*
|
||
|
* Returns the default VM stack size. Note that this is a maximum number of
|
||
|
* object in VM stack, not a size in byte.
|
||
|
*/
|
||
|
static VALUE
|
||
|
rb_fiber_s_get_default_vm_stacksize(VALUE klass)
|
||
|
{
|
||
|
return rb_ivar_get(klass, id_default_vm_stacksize);
|
||
|
}
|
||
|
/*
|
||
|
* call-seq:
|
||
|
* Fiber.default_vm_stacksize = num -> integer
|
||
|
*
|
||
|
* Sets the default VM stack size.
|
||
|
* Returns +num+.
|
||
|
* Raises TypeError if +num+ is not Numeric and
|
||
|
* raises ArgumentError if num is less than FIBER_VM_STACK_SIZE.
|
||
|
*/
|
||
|
static VALUE
|
||
|
rb_fiber_s_set_default_vm_stacksize(VALUE klass, VALUE num)
|
||
|
{
|
||
|
num = rb_to_int(num);
|
||
|
if (NUM2ULONG(num) < (unsigned long)FIBER_VM_STACK_SIZE)
|
||
|
rb_raise(rb_eArgError,
|
||
|
"Fiber default_vm_stacksize must equal or bigger than %d",
|
||
|
FIBER_VM_STACK_SIZE);
|
||
|
rb_ivar_set(klass, id_default_vm_stacksize, num);
|
||
|
return num;
|
||
|
}
|
||
|
/*
|
||
|
* Document-class: FiberError
|
||
| ... | ... | |
|
SET_MACHINE_STACK_END(&th->machine_stack_end);
|
||
|
#endif
|
||
|
id_default_vm_stacksize = rb_intern("default_vm_stacksize");
|
||
|
id_vm_stacksize = rb_intern("vm_stacksize");
|
||
|
rb_cFiber = rb_define_class("Fiber", rb_cObject);
|
||
|
rb_define_alloc_func(rb_cFiber, fiber_alloc);
|
||
|
rb_eFiberError = rb_define_class("FiberError", rb_eStandardError);
|
||
|
rb_ivar_set(rb_cFiber, id_default_vm_stacksize,
|
||
|
INT2NUM(FIBER_VM_STACK_SIZE));
|
||
|
rb_define_singleton_method(rb_cFiber, "default_vm_stacksize",
|
||
|
rb_fiber_s_get_default_vm_stacksize, 0);
|
||
|
rb_define_singleton_method(rb_cFiber, "default_vm_stacksize=",
|
||
|
rb_fiber_s_set_default_vm_stacksize, 1);
|
||
|
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, "initialize", rb_fiber_init, -1);
|
||
|
rb_define_method(rb_cFiber, "resume", rb_fiber_m_resume, -1);
|
||
|
rb_define_method(rb_cFiber, "vm_stacksize", rb_fiber_vm_stacksize, 0);
|
||
|
}
|
||
|
#if defined __GNUC__ && __GNUC__ >= 4
|
||
| test/ruby/test_fiber.rb | ||
|---|---|---|
|
end
|
||
|
assert_equal("Can't call on top of Fiber or Thread", error.message, bug5083)
|
||
|
end
|
||
|
def test_default_vm_stacksize
|
||
|
begin
|
||
|
default_vm_stacksize = Fiber.default_vm_stacksize
|
||
|
assert_equal(4*1024, default_vm_stacksize)
|
||
|
Fiber.default_vm_stacksize = 8 * 1024
|
||
|
assert_equal(8*1024, Fiber.default_vm_stacksize)
|
||
|
assert_raise(TypeError) do
|
||
|
Fiber.default_vm_stacksize = Object.new
|
||
|
end
|
||
|
assert_raise(ArgumentError) do
|
||
|
Fiber.default_vm_stacksize = 0
|
||
|
end
|
||
|
ensure
|
||
|
if default_vm_stacksize
|
||
|
Fiber.default_vm_stacksize = default_vm_stacksize
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
def test_vm_stacksize
|
||
|
fib = Fiber.new { }
|
||
|
assert_equal(Fiber.default_vm_stacksize, fib.vm_stacksize)
|
||
|
fib = Fiber.new(:vm_stacksize => 8*1024) {}
|
||
|
assert_equal(8*1024, fib.vm_stacksize)
|
||
|
assert_raise(TypeError) do
|
||
|
Fiber.new(:vm_stacksize => Object.new) {}
|
||
|
end
|
||
|
assert_raise(ArgumentError) do
|
||
|
Fiber.new(:vm_stacksize => 2 * 1024) {}
|
||
|
end
|
||
|
end
|
||
|
end
|
||