mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
manage fiber status (create|running|resumed|terminated)
This commit is contained in:
@@ -61,6 +61,13 @@ typedef struct {
|
||||
struct REnv *env;
|
||||
} 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 *prev;
|
||||
|
||||
@@ -75,6 +82,7 @@ struct mrb_context {
|
||||
struct RProc **ensure;
|
||||
int esize;
|
||||
|
||||
uint8_t status;
|
||||
struct RFiber *fib;
|
||||
};
|
||||
|
||||
|
||||
@@ -105,6 +105,7 @@ fiber_init(mrb_state *mrb, mrb_value self)
|
||||
c->ci++; /* push dummy callinfo */
|
||||
|
||||
c->fib = f;
|
||||
c->status = MRB_FIBER_CREATED;
|
||||
|
||||
return self;
|
||||
}
|
||||
@@ -153,8 +154,15 @@ fiber_resume(mrb_state *mrb, mrb_value self)
|
||||
mrb_value *a;
|
||||
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);
|
||||
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 *e = b + len;
|
||||
|
||||
@@ -163,16 +171,15 @@ fiber_resume(mrb_state *mrb, mrb_value self)
|
||||
}
|
||||
c->ci->argc = len;
|
||||
c->prev = mrb->c;
|
||||
c->status = MRB_FIBER_RUNNING;
|
||||
mrb->c = c;
|
||||
|
||||
MARK_CONTEXT_MODIFY(c);
|
||||
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);
|
||||
c->prev = mrb->c;
|
||||
c->status = MRB_FIBER_RUNNING;
|
||||
mrb->c = c;
|
||||
return fiber_result(mrb, a, len);
|
||||
}
|
||||
@@ -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_get_args(mrb, "*", &a, &len);
|
||||
|
||||
c->prev->status = MRB_FIBER_RUNNING;
|
||||
mrb->c = c->prev;
|
||||
c->prev = NULL;
|
||||
MARK_CONTEXT_MODIFY(mrb->c);
|
||||
return fiber_result(mrb, a, len);
|
||||
}
|
||||
|
||||
@@ -1301,7 +1301,14 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
|
||||
localjump_error(mrb, LOCALJUMP_ERROR_RETURN);
|
||||
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;
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user