mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* cont.c: separate data structure between rb_fiber_t and
rb_context_t (rb_fiber_t includes rb_context_t). rb_fiber_t has double linked list of fibers in same threads. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@19890 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
d1c4aefa62
commit
8a0d53ac2b
3 changed files with 161 additions and 71 deletions
|
@ -1,3 +1,9 @@
|
||||||
|
Thu Oct 23 00:10:01 2008 Koichi Sasada <ko1@atdot.net>
|
||||||
|
|
||||||
|
* cont.c: separate data structure between rb_fiber_t and
|
||||||
|
rb_context_t (rb_fiber_t includes rb_context_t).
|
||||||
|
rb_fiber_t has double linked list of fibers in same threads.
|
||||||
|
|
||||||
Wed Oct 22 17:25:17 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
|
Wed Oct 22 17:25:17 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
|
||||||
|
|
||||||
* io.c (pipe_open): remove unnecessary flush before fork.
|
* io.c (pipe_open): remove unnecessary flush before fork.
|
||||||
|
|
220
cont.c
220
cont.c
|
@ -21,6 +21,7 @@ enum context_type {
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct rb_context_struct {
|
typedef struct rb_context_struct {
|
||||||
|
enum context_type type;
|
||||||
VALUE self;
|
VALUE self;
|
||||||
VALUE value;
|
VALUE value;
|
||||||
VALUE *vm_stack;
|
VALUE *vm_stack;
|
||||||
|
@ -34,11 +35,22 @@ typedef struct rb_context_struct {
|
||||||
rb_thread_t saved_thread;
|
rb_thread_t saved_thread;
|
||||||
rb_jmpbuf_t jmpbuf;
|
rb_jmpbuf_t jmpbuf;
|
||||||
int machine_stack_size;
|
int machine_stack_size;
|
||||||
VALUE prev;
|
|
||||||
int alive;
|
|
||||||
enum context_type type;
|
|
||||||
} rb_context_t;
|
} rb_context_t;
|
||||||
|
|
||||||
|
enum fiber_status {
|
||||||
|
CREATED,
|
||||||
|
RUNNING,
|
||||||
|
TERMINATED,
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct rb_fiber_struct {
|
||||||
|
rb_context_t cont;
|
||||||
|
VALUE prev;
|
||||||
|
enum fiber_status status;
|
||||||
|
struct rb_fiber_struct *prev_fiber;
|
||||||
|
struct rb_fiber_struct *next_fiber;
|
||||||
|
} rb_fiber_t;
|
||||||
|
|
||||||
static VALUE rb_cContinuation;
|
static VALUE rb_cContinuation;
|
||||||
static VALUE rb_cFiber;
|
static VALUE rb_cFiber;
|
||||||
static VALUE rb_eFiberError;
|
static VALUE rb_eFiberError;
|
||||||
|
@ -46,6 +58,9 @@ static VALUE rb_eFiberError;
|
||||||
#define GetContPtr(obj, ptr) \
|
#define GetContPtr(obj, ptr) \
|
||||||
Data_Get_Struct(obj, rb_context_t, ptr)
|
Data_Get_Struct(obj, rb_context_t, ptr)
|
||||||
|
|
||||||
|
#define GetFiberPtr(obj, ptr) \
|
||||||
|
Data_Get_Struct(obj, rb_fiber_t, ptr)
|
||||||
|
|
||||||
NOINLINE(static VALUE cont_capture(volatile int *stat));
|
NOINLINE(static VALUE cont_capture(volatile int *stat));
|
||||||
|
|
||||||
void rb_thread_mark(rb_thread_t *th);
|
void rb_thread_mark(rb_thread_t *th);
|
||||||
|
@ -57,7 +72,6 @@ cont_mark(void *ptr)
|
||||||
if (ptr) {
|
if (ptr) {
|
||||||
rb_context_t *cont = ptr;
|
rb_context_t *cont = ptr;
|
||||||
rb_gc_mark(cont->value);
|
rb_gc_mark(cont->value);
|
||||||
rb_gc_mark(cont->prev);
|
|
||||||
rb_thread_mark(&cont->saved_thread);
|
rb_thread_mark(&cont->saved_thread);
|
||||||
|
|
||||||
if (cont->vm_stack) {
|
if (cont->vm_stack) {
|
||||||
|
@ -85,22 +99,69 @@ cont_free(void *ptr)
|
||||||
RUBY_FREE_ENTER("cont");
|
RUBY_FREE_ENTER("cont");
|
||||||
if (ptr) {
|
if (ptr) {
|
||||||
rb_context_t *cont = ptr;
|
rb_context_t *cont = ptr;
|
||||||
RUBY_FREE_UNLESS_NULL(cont->saved_thread.stack);
|
RUBY_FREE_UNLESS_NULL(cont->saved_thread.stack); fflush(stdout);
|
||||||
RUBY_FREE_UNLESS_NULL(cont->machine_stack);
|
RUBY_FREE_UNLESS_NULL(cont->machine_stack);
|
||||||
#ifdef __ia64
|
#ifdef __ia64
|
||||||
RUBY_FREE_UNLESS_NULL(cont->machine_register_stack);
|
RUBY_FREE_UNLESS_NULL(cont->machine_register_stack);
|
||||||
#endif
|
#endif
|
||||||
RUBY_FREE_UNLESS_NULL(cont->vm_stack);
|
RUBY_FREE_UNLESS_NULL(cont->vm_stack);
|
||||||
|
|
||||||
if (cont->type == FIBER_CONTEXT) {
|
/* free rb_cont_t or rb_fiber_t */
|
||||||
st_free_table(cont->saved_thread.local_storage);
|
|
||||||
}
|
|
||||||
|
|
||||||
ruby_xfree(ptr);
|
ruby_xfree(ptr);
|
||||||
}
|
}
|
||||||
RUBY_FREE_LEAVE("cont");
|
RUBY_FREE_LEAVE("cont");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fiber_mark(void *ptr)
|
||||||
|
{
|
||||||
|
RUBY_MARK_ENTER("cont");
|
||||||
|
if (ptr) {
|
||||||
|
rb_fiber_t *fib = ptr;
|
||||||
|
rb_gc_mark(fib->prev);
|
||||||
|
cont_mark(&fib->cont);
|
||||||
|
}
|
||||||
|
RUBY_MARK_LEAVE("cont");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fiber_link_join(rb_fiber_t *fib)
|
||||||
|
{
|
||||||
|
VALUE current_fibval = rb_fiber_current();
|
||||||
|
rb_fiber_t *current_fib;
|
||||||
|
GetFiberPtr(current_fibval, current_fib);
|
||||||
|
|
||||||
|
/* join fiber link */
|
||||||
|
fib->next_fiber = current_fib->next_fiber;
|
||||||
|
fib->prev_fiber = current_fib;
|
||||||
|
current_fib->next_fiber->prev_fiber = fib;
|
||||||
|
current_fib->next_fiber = fib;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fiber_link_remove(rb_fiber_t *fib)
|
||||||
|
{
|
||||||
|
fib->prev_fiber->next_fiber = fib->next_fiber;
|
||||||
|
fib->next_fiber->prev_fiber = fib->prev_fiber;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fiber_free(void *ptr)
|
||||||
|
{
|
||||||
|
RUBY_FREE_ENTER("fiber");
|
||||||
|
if (ptr) {
|
||||||
|
rb_fiber_t *fib = ptr;
|
||||||
|
|
||||||
|
if (fib->cont.type != ROOT_FIBER_CONTEXT) {
|
||||||
|
st_free_table(fib->cont.saved_thread.local_storage);
|
||||||
|
}
|
||||||
|
fiber_link_remove(fib);
|
||||||
|
|
||||||
|
cont_free(&fib->cont);
|
||||||
|
}
|
||||||
|
RUBY_FREE_LEAVE("fiber");
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
cont_save_machine_stack(rb_thread_t *th, rb_context_t *cont)
|
cont_save_machine_stack(rb_thread_t *th, rb_context_t *cont)
|
||||||
{
|
{
|
||||||
|
@ -151,21 +212,24 @@ cont_save_machine_stack(rb_thread_t *th, rb_context_t *cont)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
cont_init(rb_context_t *cont)
|
||||||
|
{
|
||||||
|
rb_thread_t *th = GET_THREAD();
|
||||||
|
|
||||||
|
/* save thread context */
|
||||||
|
cont->saved_thread = *th;
|
||||||
|
}
|
||||||
|
|
||||||
static rb_context_t *
|
static rb_context_t *
|
||||||
cont_new(VALUE klass)
|
cont_new(VALUE klass)
|
||||||
{
|
{
|
||||||
rb_context_t *cont;
|
rb_context_t *cont;
|
||||||
volatile VALUE contval;
|
volatile VALUE contval;
|
||||||
rb_thread_t *th = GET_THREAD();
|
|
||||||
|
|
||||||
contval = Data_Make_Struct(klass, rb_context_t, cont_mark, cont_free, cont);
|
contval = Data_Make_Struct(klass, rb_context_t, cont_mark, cont_free, cont);
|
||||||
|
|
||||||
cont->self = contval;
|
cont->self = contval;
|
||||||
cont->alive = Qtrue;
|
cont_init(cont);
|
||||||
|
|
||||||
/* save thread context */
|
|
||||||
cont->saved_thread = *th;
|
|
||||||
|
|
||||||
return cont;
|
return cont;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -465,10 +529,6 @@ rb_cont_call(int argc, VALUE *argv, VALUE contval)
|
||||||
if (th->fiber != cont->saved_thread.fiber) {
|
if (th->fiber != cont->saved_thread.fiber) {
|
||||||
rb_raise(rb_eRuntimeError, "continuation called across fiber");
|
rb_raise(rb_eRuntimeError, "continuation called across fiber");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!fcont->alive) {
|
|
||||||
rb_raise(rb_eRuntimeError, "continuation called dead fiber");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cont->value = make_passing_arg(argc, argv);
|
cont->value = make_passing_arg(argc, argv);
|
||||||
|
@ -483,25 +543,32 @@ rb_cont_call(int argc, VALUE *argv, VALUE contval)
|
||||||
|
|
||||||
#define FIBER_VM_STACK_SIZE (4 * 1024)
|
#define FIBER_VM_STACK_SIZE (4 * 1024)
|
||||||
|
|
||||||
static rb_context_t *
|
static rb_fiber_t *
|
||||||
fiber_alloc(VALUE klass)
|
fiber_alloc(VALUE klass)
|
||||||
{
|
{
|
||||||
rb_context_t *cont = cont_new(klass);
|
rb_fiber_t *fib;
|
||||||
|
volatile VALUE fibval = Data_Make_Struct(klass, rb_fiber_t, fiber_mark, fiber_free, fib);
|
||||||
|
|
||||||
cont->type = FIBER_CONTEXT;
|
fib->cont.self = fibval;
|
||||||
cont->prev = Qnil;
|
fib->cont.type = FIBER_CONTEXT;
|
||||||
|
cont_init(&fib->cont);
|
||||||
|
fib->prev = Qnil;
|
||||||
|
fib->status = CREATED;
|
||||||
|
|
||||||
return cont;
|
return fib;
|
||||||
}
|
}
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
fiber_new(VALUE klass, VALUE proc)
|
fiber_new(VALUE klass, VALUE proc)
|
||||||
{
|
{
|
||||||
rb_context_t *cont = fiber_alloc(klass);
|
rb_fiber_t *fib = fiber_alloc(klass);
|
||||||
VALUE contval = cont->self;
|
VALUE fibval = fib->cont.self;
|
||||||
|
rb_context_t *cont = &fib->cont;
|
||||||
rb_thread_t *th = &cont->saved_thread;
|
rb_thread_t *th = &cont->saved_thread;
|
||||||
|
|
||||||
/* initialize */
|
fiber_link_join(fib);
|
||||||
|
|
||||||
|
/* initialize cont */
|
||||||
cont->vm_stack = 0;
|
cont->vm_stack = 0;
|
||||||
|
|
||||||
th->stack = 0;
|
th->stack = 0;
|
||||||
|
@ -528,7 +595,7 @@ fiber_new(VALUE klass, VALUE proc)
|
||||||
|
|
||||||
MEMCPY(&cont->jmpbuf, &th->root_jmpbuf, rb_jmpbuf_t, 1);
|
MEMCPY(&cont->jmpbuf, &th->root_jmpbuf, rb_jmpbuf_t, 1);
|
||||||
|
|
||||||
return contval;
|
return fibval;
|
||||||
}
|
}
|
||||||
|
|
||||||
VALUE
|
VALUE
|
||||||
|
@ -546,11 +613,11 @@ rb_fiber_s_new(VALUE self)
|
||||||
static VALUE
|
static VALUE
|
||||||
return_fiber(void)
|
return_fiber(void)
|
||||||
{
|
{
|
||||||
rb_context_t *cont;
|
rb_fiber_t *fib;
|
||||||
VALUE curr = rb_fiber_current();
|
VALUE curr = rb_fiber_current();
|
||||||
GetContPtr(curr, cont);
|
GetFiberPtr(curr, fib);
|
||||||
|
|
||||||
if (cont->prev == Qnil) {
|
if (fib->prev == Qnil) {
|
||||||
rb_thread_t *th = GET_THREAD();
|
rb_thread_t *th = GET_THREAD();
|
||||||
|
|
||||||
if (th->root_fiber != curr) {
|
if (th->root_fiber != curr) {
|
||||||
|
@ -561,8 +628,8 @@ return_fiber(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
VALUE prev = cont->prev;
|
VALUE prev = fib->prev;
|
||||||
cont->prev = Qnil;
|
fib->prev = Qnil;
|
||||||
return prev;
|
return prev;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -570,10 +637,10 @@ return_fiber(void)
|
||||||
VALUE rb_fiber_transfer(VALUE fib, int argc, VALUE *argv);
|
VALUE rb_fiber_transfer(VALUE fib, int argc, VALUE *argv);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
rb_fiber_terminate(rb_context_t *cont)
|
rb_fiber_terminate(rb_fiber_t *fib)
|
||||||
{
|
{
|
||||||
VALUE value = cont->value;
|
VALUE value = fib->cont.value;
|
||||||
cont->alive = Qfalse;
|
fib->status = TERMINATED;
|
||||||
rb_fiber_transfer(return_fiber(), 1, &value);
|
rb_fiber_transfer(return_fiber(), 1, &value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -581,12 +648,15 @@ void
|
||||||
rb_fiber_start(void)
|
rb_fiber_start(void)
|
||||||
{
|
{
|
||||||
rb_thread_t *th = GET_THREAD();
|
rb_thread_t *th = GET_THREAD();
|
||||||
|
rb_fiber_t *fib;
|
||||||
rb_context_t *cont;
|
rb_context_t *cont;
|
||||||
rb_proc_t *proc;
|
rb_proc_t *proc;
|
||||||
VALUE args;
|
VALUE args;
|
||||||
int state;
|
int state;
|
||||||
|
|
||||||
GetContPtr(th->fiber, cont);
|
GetFiberPtr(th->fiber, fib);
|
||||||
|
cont = &fib->cont;
|
||||||
|
|
||||||
TH_PUSH_TAG(th);
|
TH_PUSH_TAG(th);
|
||||||
if ((state = EXEC_TAG()) == 0) {
|
if ((state = EXEC_TAG()) == 0) {
|
||||||
GetProcPtr(cont->saved_thread.first_proc, proc);
|
GetProcPtr(cont->saved_thread.first_proc, proc);
|
||||||
|
@ -596,6 +666,7 @@ rb_fiber_start(void)
|
||||||
th->local_lfp = proc->block.lfp;
|
th->local_lfp = proc->block.lfp;
|
||||||
th->local_svar = Qnil;
|
th->local_svar = Qnil;
|
||||||
|
|
||||||
|
fib->status = RUNNING;
|
||||||
cont->value = vm_invoke_proc(th, proc, proc->block.self, 1, &args, 0);
|
cont->value = vm_invoke_proc(th, proc, proc->block.self, 1, &args, 0);
|
||||||
}
|
}
|
||||||
TH_POP_TAG();
|
TH_POP_TAG();
|
||||||
|
@ -611,46 +682,57 @@ rb_fiber_start(void)
|
||||||
RUBY_VM_SET_INTERRUPT(th);
|
RUBY_VM_SET_INTERRUPT(th);
|
||||||
}
|
}
|
||||||
|
|
||||||
rb_fiber_terminate(cont);
|
rb_fiber_terminate(fib);
|
||||||
rb_bug("rb_fiber_start: unreachable");
|
rb_bug("rb_fiber_start: unreachable");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static rb_fiber_t *
|
||||||
|
root_fiber_alloc(rb_thread_t *th)
|
||||||
|
{
|
||||||
|
rb_fiber_t *fib;
|
||||||
|
|
||||||
|
/* no need to allocate vm stack */
|
||||||
|
fib = fiber_alloc(rb_cFiber);
|
||||||
|
fib->cont.type = ROOT_FIBER_CONTEXT;
|
||||||
|
fib->prev_fiber = fib->next_fiber = fib;
|
||||||
|
|
||||||
|
return fib;
|
||||||
|
}
|
||||||
|
|
||||||
VALUE
|
VALUE
|
||||||
rb_fiber_current()
|
rb_fiber_current()
|
||||||
{
|
{
|
||||||
rb_thread_t *th = GET_THREAD();
|
rb_thread_t *th = GET_THREAD();
|
||||||
if (th->fiber == 0) {
|
if (th->fiber == 0) {
|
||||||
/* save root */
|
/* save root */
|
||||||
rb_context_t *cont = fiber_alloc(rb_cFiber);
|
rb_fiber_t *fib = root_fiber_alloc(th);
|
||||||
cont->type = ROOT_FIBER_CONTEXT;
|
th->root_fiber = th->fiber = fib->cont.self;
|
||||||
th->root_fiber = th->fiber = cont->self;
|
|
||||||
}
|
}
|
||||||
return th->fiber;
|
return th->fiber;
|
||||||
}
|
}
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
fiber_store(rb_context_t *next_cont)
|
fiber_store(rb_fiber_t *next_fib)
|
||||||
{
|
{
|
||||||
rb_thread_t *th = GET_THREAD();
|
rb_thread_t *th = GET_THREAD();
|
||||||
rb_context_t *cont;
|
rb_fiber_t *fib;
|
||||||
|
|
||||||
if (th->fiber) {
|
if (th->fiber) {
|
||||||
GetContPtr(th->fiber, cont);
|
GetFiberPtr(th->fiber, fib);
|
||||||
cont->saved_thread = *th;
|
fib->cont.saved_thread = *th;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* create current fiber */
|
/* create current fiber */
|
||||||
cont = fiber_alloc(rb_cFiber); /* no need to allocate vm stack */
|
fib = root_fiber_alloc(th);
|
||||||
cont->type = ROOT_FIBER_CONTEXT;
|
th->root_fiber = th->fiber = fib->cont.self;
|
||||||
th->root_fiber = th->fiber = cont->self;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cont_save_machine_stack(th, cont);
|
cont_save_machine_stack(th, &fib->cont);
|
||||||
|
|
||||||
if (ruby_setjmp(cont->jmpbuf)) {
|
if (ruby_setjmp(fib->cont.jmpbuf)) {
|
||||||
/* restored */
|
/* restored */
|
||||||
GetContPtr(th->fiber, cont);
|
GetFiberPtr(th->fiber, fib);
|
||||||
return cont->value;
|
return fib->cont.value;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return Qundef;
|
return Qundef;
|
||||||
|
@ -658,13 +740,15 @@ fiber_store(rb_context_t *next_cont)
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline VALUE
|
static inline VALUE
|
||||||
fiber_switch(VALUE fib, int argc, VALUE *argv, int is_resume)
|
fiber_switch(VALUE fibval, int argc, VALUE *argv, int is_resume)
|
||||||
{
|
{
|
||||||
VALUE value;
|
VALUE value;
|
||||||
|
rb_fiber_t *fib;
|
||||||
rb_context_t *cont;
|
rb_context_t *cont;
|
||||||
rb_thread_t *th = GET_THREAD();
|
rb_thread_t *th = GET_THREAD();
|
||||||
|
|
||||||
GetContPtr(fib, cont);
|
GetFiberPtr(fibval, fib);
|
||||||
|
cont = &fib->cont;
|
||||||
|
|
||||||
if (cont->saved_thread.self != th->self) {
|
if (cont->saved_thread.self != th->self) {
|
||||||
rb_raise(rb_eFiberError, "fiber called across threads");
|
rb_raise(rb_eFiberError, "fiber called across threads");
|
||||||
|
@ -672,18 +756,18 @@ fiber_switch(VALUE fib, int argc, VALUE *argv, int is_resume)
|
||||||
else if (cont->saved_thread.trap_tag != th->trap_tag) {
|
else if (cont->saved_thread.trap_tag != th->trap_tag) {
|
||||||
rb_raise(rb_eFiberError, "fiber called across trap");
|
rb_raise(rb_eFiberError, "fiber called across trap");
|
||||||
}
|
}
|
||||||
else if (!cont->alive) {
|
else if (fib->status == TERMINATED) {
|
||||||
rb_raise(rb_eFiberError, "dead fiber called");
|
rb_raise(rb_eFiberError, "dead fiber called");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_resume) {
|
if (is_resume) {
|
||||||
cont->prev = rb_fiber_current();
|
fib->prev = rb_fiber_current();
|
||||||
}
|
}
|
||||||
|
|
||||||
cont->value = make_passing_arg(argc, argv);
|
cont->value = make_passing_arg(argc, argv);
|
||||||
|
|
||||||
if ((value = fiber_store(cont)) == Qundef) {
|
if ((value = fiber_store(fib)) == Qundef) {
|
||||||
cont_restore_0(cont, &value);
|
cont_restore_0(&fib->cont, &value);
|
||||||
rb_bug("rb_fiber_resume: unreachable");
|
rb_bug("rb_fiber_resume: unreachable");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -699,16 +783,16 @@ rb_fiber_transfer(VALUE fib, int argc, VALUE *argv)
|
||||||
}
|
}
|
||||||
|
|
||||||
VALUE
|
VALUE
|
||||||
rb_fiber_resume(VALUE fib, int argc, VALUE *argv)
|
rb_fiber_resume(VALUE fibval, int argc, VALUE *argv)
|
||||||
{
|
{
|
||||||
rb_context_t *cont;
|
rb_fiber_t *fib;
|
||||||
GetContPtr(fib, cont);
|
GetFiberPtr(fibval, fib);
|
||||||
|
|
||||||
if (cont->prev != Qnil) {
|
if (fib->prev != Qnil) {
|
||||||
rb_raise(rb_eFiberError, "double resume");
|
rb_raise(rb_eFiberError, "double resume");
|
||||||
}
|
}
|
||||||
|
|
||||||
return fiber_switch(fib, argc, argv, 1);
|
return fiber_switch(fibval, argc, argv, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
VALUE
|
VALUE
|
||||||
|
@ -718,11 +802,11 @@ rb_fiber_yield(int argc, VALUE *argv)
|
||||||
}
|
}
|
||||||
|
|
||||||
VALUE
|
VALUE
|
||||||
rb_fiber_alive_p(VALUE fib)
|
rb_fiber_alive_p(VALUE fibval)
|
||||||
{
|
{
|
||||||
rb_context_t *cont;
|
rb_fiber_t *fib;
|
||||||
GetContPtr(fib, cont);
|
GetFiberPtr(fibval, fib);
|
||||||
return cont->alive;
|
return fib->status != TERMINATED;
|
||||||
}
|
}
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#define RUBY_VERSION "1.9.0"
|
#define RUBY_VERSION "1.9.0"
|
||||||
#define RUBY_RELEASE_DATE "2008-10-22"
|
#define RUBY_RELEASE_DATE "2008-10-23"
|
||||||
#define RUBY_VERSION_CODE 190
|
#define RUBY_VERSION_CODE 190
|
||||||
#define RUBY_RELEASE_CODE 20081022
|
#define RUBY_RELEASE_CODE 20081023
|
||||||
#define RUBY_PATCHLEVEL 0
|
#define RUBY_PATCHLEVEL 0
|
||||||
|
|
||||||
#define RUBY_VERSION_MAJOR 1
|
#define RUBY_VERSION_MAJOR 1
|
||||||
|
@ -9,7 +9,7 @@
|
||||||
#define RUBY_VERSION_TEENY 0
|
#define RUBY_VERSION_TEENY 0
|
||||||
#define RUBY_RELEASE_YEAR 2008
|
#define RUBY_RELEASE_YEAR 2008
|
||||||
#define RUBY_RELEASE_MONTH 10
|
#define RUBY_RELEASE_MONTH 10
|
||||||
#define RUBY_RELEASE_DAY 22
|
#define RUBY_RELEASE_DAY 23
|
||||||
|
|
||||||
#ifdef RUBY_EXTERN
|
#ifdef RUBY_EXTERN
|
||||||
RUBY_EXTERN const char ruby_version[];
|
RUBY_EXTERN const char ruby_version[];
|
||||||
|
|
Loading…
Reference in a new issue