manage fiber status (create|running|resumed|terminated)

parent 93d71011
...@@ -61,6 +61,13 @@ typedef struct { ...@@ -61,6 +61,13 @@ typedef struct {
struct REnv *env; struct REnv *env;
} mrb_callinfo; } mrb_callinfo;
enum mrb_fiber_state {
MRB_FIBER_CREATED = 0,
MRB_FIBER_RUNNING,
MRB_FIBER_RESUMED,
MRB_FIBER_TERMINATED,
};
struct mrb_context { struct mrb_context {
struct mrb_context *prev; struct mrb_context *prev;
...@@ -75,6 +82,7 @@ struct mrb_context { ...@@ -75,6 +82,7 @@ struct mrb_context {
struct RProc **ensure; struct RProc **ensure;
int esize; int esize;
uint8_t status;
struct RFiber *fib; struct RFiber *fib;
}; };
......
...@@ -105,6 +105,7 @@ fiber_init(mrb_state *mrb, mrb_value self) ...@@ -105,6 +105,7 @@ fiber_init(mrb_state *mrb, mrb_value self)
c->ci++; /* push dummy callinfo */ c->ci++; /* push dummy callinfo */
c->fib = f; c->fib = f;
c->status = MRB_FIBER_CREATED;
return self; return self;
} }
...@@ -153,8 +154,15 @@ fiber_resume(mrb_state *mrb, mrb_value self) ...@@ -153,8 +154,15 @@ fiber_resume(mrb_state *mrb, mrb_value self)
mrb_value *a; mrb_value *a;
int len; int len;
if (c->status == MRB_FIBER_RESUMED) {
mrb_raise(mrb, E_RUNTIME_ERROR, "double resume");
}
if (c->status == MRB_FIBER_TERMINATED) {
mrb_raise(mrb, E_RUNTIME_ERROR, "resuming dead fiber");
}
mrb_get_args(mrb, "*", &a, &len); mrb_get_args(mrb, "*", &a, &len);
if (!c->prev) { /* first call */ mrb->c->status = MRB_FIBER_RESUMED;
if (c->status == MRB_FIBER_CREATED) {
mrb_value *b = c->stack+1; mrb_value *b = c->stack+1;
mrb_value *e = b + len; mrb_value *e = b + len;
...@@ -163,16 +171,15 @@ fiber_resume(mrb_state *mrb, mrb_value self) ...@@ -163,16 +171,15 @@ fiber_resume(mrb_state *mrb, mrb_value self)
} }
c->ci->argc = len; c->ci->argc = len;
c->prev = mrb->c; c->prev = mrb->c;
c->status = MRB_FIBER_RUNNING;
mrb->c = c; mrb->c = c;
MARK_CONTEXT_MODIFY(c); MARK_CONTEXT_MODIFY(c);
return c->ci->proc->env->stack[0]; return c->ci->proc->env->stack[0];
} }
if (c->ci == c->cibase) {
mrb_raise(mrb, E_RUNTIME_ERROR, "resuming dead fiber");
}
MARK_CONTEXT_MODIFY(c); MARK_CONTEXT_MODIFY(c);
c->prev = mrb->c; c->prev = mrb->c;
c->status = MRB_FIBER_RUNNING;
mrb->c = c; mrb->c = c;
return fiber_result(mrb, a, len); return fiber_result(mrb, a, len);
} }
...@@ -198,8 +205,9 @@ fiber_yield(mrb_state *mrb, mrb_value self) ...@@ -198,8 +205,9 @@ fiber_yield(mrb_state *mrb, mrb_value self)
mrb_raise(mrb, E_ARGUMENT_ERROR, "can't yield from root fiber"); mrb_raise(mrb, E_ARGUMENT_ERROR, "can't yield from root fiber");
} }
mrb_get_args(mrb, "*", &a, &len); mrb_get_args(mrb, "*", &a, &len);
c->prev->status = MRB_FIBER_RUNNING;
mrb->c = c->prev; mrb->c = c->prev;
c->prev = NULL;
MARK_CONTEXT_MODIFY(mrb->c); MARK_CONTEXT_MODIFY(mrb->c);
return fiber_result(mrb, a, len); return fiber_result(mrb, a, len);
} }
......
...@@ -1301,7 +1301,14 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) ...@@ -1301,7 +1301,14 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
localjump_error(mrb, LOCALJUMP_ERROR_RETURN); localjump_error(mrb, LOCALJUMP_ERROR_RETURN);
goto L_RAISE; goto L_RAISE;
} }
mrb->c = mrb->c->prev; /* automatic yield at the end */ if (mrb->c->prev->ci == mrb->c->prev->cibase) {
mrb_value exc = mrb_exc_new3(mrb, E_RUNTIME_ERROR, mrb_str_new(mrb, "double resume", 13));
mrb->exc = mrb_obj_ptr(exc);
goto L_RAISE;
}
/* automatic yield at the end */
mrb->c->status = MRB_FIBER_TERMINATED;
mrb->c = mrb->c->prev;
} }
ci = mrb->c->ci; ci = mrb->c->ci;
break; break;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment