summaryrefslogtreecommitdiffstats
path: root/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-fiber/src/fiber.c
diff options
context:
space:
mode:
Diffstat (limited to 'web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-fiber/src/fiber.c')
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-fiber/src/fiber.c420
1 files changed, 0 insertions, 420 deletions
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-fiber/src/fiber.c b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-fiber/src/fiber.c
deleted file mode 100644
index 9de175f34..000000000
--- a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-fiber/src/fiber.c
+++ /dev/null
@@ -1,420 +0,0 @@
-#include <mruby.h>
-#include <mruby/array.h>
-#include <mruby/class.h>
-#include <mruby/proc.h>
-
-#define fiber_ptr(o) ((struct RFiber*)mrb_ptr(o))
-
-#define FIBER_STACK_INIT_SIZE 64
-#define FIBER_CI_INIT_SIZE 8
-#define CI_ACC_RESUMED -3
-
-/*
- * call-seq:
- * Fiber.new{...} -> obj
- *
- * Creates a fiber, whose execution is suspend until it is explicitly
- * resumed using <code>Fiber#resume</code> method.
- * The code running inside the fiber can give up control by calling
- * <code>Fiber.yield</code> in which case it yields control back to caller
- * (the caller of the <code>Fiber#resume</code>).
- *
- * Upon yielding or termination the Fiber returns the value of the last
- * executed expression
- *
- * For instance:
- *
- * fiber = Fiber.new do
- * Fiber.yield 1
- * 2
- * end
- *
- * puts fiber.resume
- * puts fiber.resume
- * puts fiber.resume
- *
- * <em>produces</em>
- *
- * 1
- * 2
- * resuming dead fiber (FiberError)
- *
- * The <code>Fiber#resume</code> method accepts an arbitrary number of
- * parameters, if it is the first call to <code>resume</code> then they
- * will be passed as block arguments. Otherwise they will be the return
- * value of the call to <code>Fiber.yield</code>
- *
- * Example:
- *
- * fiber = Fiber.new do |first|
- * second = Fiber.yield first + 2
- * end
- *
- * puts fiber.resume 10
- * puts fiber.resume 14
- * puts fiber.resume 18
- *
- * <em>produces</em>
- *
- * 12
- * 14
- * resuming dead fiber (FiberError)
- *
- */
-static mrb_value
-fiber_init(mrb_state *mrb, mrb_value self)
-{
- static const struct mrb_context mrb_context_zero = { 0 };
- struct RFiber *f = fiber_ptr(self);
- struct mrb_context *c;
- struct RProc *p;
- mrb_callinfo *ci;
- mrb_value blk;
- size_t slen;
-
- mrb_get_args(mrb, "&", &blk);
-
- if (f->cxt) {
- mrb_raise(mrb, E_RUNTIME_ERROR, "cannot initialize twice");
- }
- if (mrb_nil_p(blk)) {
- mrb_raise(mrb, E_ARGUMENT_ERROR, "tried to create Fiber object without a block");
- }
- p = mrb_proc_ptr(blk);
- if (MRB_PROC_CFUNC_P(p)) {
- mrb_raise(mrb, E_FIBER_ERROR, "tried to create Fiber from C defined method");
- }
-
- c = (struct mrb_context*)mrb_malloc(mrb, sizeof(struct mrb_context));
- *c = mrb_context_zero;
- f->cxt = c;
-
- /* initialize VM stack */
- slen = FIBER_STACK_INIT_SIZE;
- if (p->body.irep->nregs > slen) {
- slen += p->body.irep->nregs;
- }
- c->stbase = (mrb_value *)mrb_malloc(mrb, slen*sizeof(mrb_value));
- c->stend = c->stbase + slen;
- c->stack = c->stbase;
-
-#ifdef MRB_NAN_BOXING
- {
- mrb_value *p = c->stbase;
- mrb_value *pend = c->stend;
-
- while (p < pend) {
- SET_NIL_VALUE(*p);
- p++;
- }
- }
-#else
- memset(c->stbase, 0, slen * sizeof(mrb_value));
-#endif
-
- /* copy receiver from a block */
- c->stack[0] = mrb->c->stack[0];
-
- /* initialize callinfo stack */
- c->cibase = (mrb_callinfo *)mrb_calloc(mrb, FIBER_CI_INIT_SIZE, sizeof(mrb_callinfo));
- c->ciend = c->cibase + FIBER_CI_INIT_SIZE;
- c->ci = c->cibase;
- c->ci->stackent = c->stack;
-
- /* adjust return callinfo */
- ci = c->ci;
- ci->target_class = p->target_class;
- ci->proc = p;
- mrb_field_write_barrier(mrb, (struct RBasic*)mrb_obj_ptr(self), (struct RBasic*)p);
- ci->pc = p->body.irep->iseq;
- ci->nregs = p->body.irep->nregs;
- ci[1] = ci[0];
- c->ci++; /* push dummy callinfo */
-
- c->fib = f;
- c->status = MRB_FIBER_CREATED;
-
- return self;
-}
-
-static struct mrb_context*
-fiber_check(mrb_state *mrb, mrb_value fib)
-{
- struct RFiber *f = fiber_ptr(fib);
-
- mrb_assert(f->tt == MRB_TT_FIBER);
- if (!f->cxt) {
- mrb_raise(mrb, E_FIBER_ERROR, "uninitialized Fiber");
- }
- return f->cxt;
-}
-
-static mrb_value
-fiber_result(mrb_state *mrb, const mrb_value *a, mrb_int len)
-{
- if (len == 0) return mrb_nil_value();
- if (len == 1) return a[0];
- return mrb_ary_new_from_values(mrb, len, a);
-}
-
-/* mark return from context modifying method */
-#define MARK_CONTEXT_MODIFY(c) (c)->ci->target_class = NULL
-
-static void
-fiber_check_cfunc(mrb_state *mrb, struct mrb_context *c)
-{
- mrb_callinfo *ci;
-
- for (ci = c->ci; ci >= c->cibase; ci--) {
- if (ci->acc < 0) {
- mrb_raise(mrb, E_FIBER_ERROR, "can't cross C function boundary");
- }
- }
-}
-
-static void
-fiber_switch_context(mrb_state *mrb, struct mrb_context *c)
-{
- if (mrb->c->fib) {
- mrb_write_barrier(mrb, (struct RBasic*)mrb->c->fib);
- }
- c->status = MRB_FIBER_RUNNING;
- mrb->c = c;
-}
-
-static mrb_value
-fiber_switch(mrb_state *mrb, mrb_value self, mrb_int len, const mrb_value *a, mrb_bool resume, mrb_bool vmexec)
-{
- struct mrb_context *c = fiber_check(mrb, self);
- struct mrb_context *old_c = mrb->c;
- mrb_value value;
-
- fiber_check_cfunc(mrb, c);
- if (resume && c->status == MRB_FIBER_TRANSFERRED) {
- mrb_raise(mrb, E_FIBER_ERROR, "resuming transferred fiber");
- }
- if (c->status == MRB_FIBER_RUNNING || c->status == MRB_FIBER_RESUMED) {
- mrb_raise(mrb, E_FIBER_ERROR, "double resume (fib)");
- }
- if (c->status == MRB_FIBER_TERMINATED) {
- mrb_raise(mrb, E_FIBER_ERROR, "resuming dead fiber");
- }
- mrb->c->status = resume ? MRB_FIBER_RESUMED : MRB_FIBER_TRANSFERRED;
- c->prev = resume ? mrb->c : (c->prev ? c->prev : mrb->root_c);
- if (c->status == MRB_FIBER_CREATED) {
- mrb_value *b, *e;
-
- if (len >= c->stend - c->stack) {
- mrb_raise(mrb, E_FIBER_ERROR, "too many arguments to fiber");
- }
- b = c->stack+1;
- e = b + len;
- while (b<e) {
- *b++ = *a++;
- }
- c->cibase->argc = len;
- value = c->stack[0] = c->ci->proc->env->stack[0];
- }
- else {
- value = fiber_result(mrb, a, len);
- }
- fiber_switch_context(mrb, c);
-
- if (vmexec) {
- c->vmexec = TRUE;
- value = mrb_vm_exec(mrb, c->ci[-1].proc, c->ci->pc);
- mrb->c = old_c;
- }
- else {
- MARK_CONTEXT_MODIFY(c);
- }
- return value;
-}
-
-/*
- * call-seq:
- * fiber.resume(args, ...) -> obj
- *
- * Resumes the fiber from the point at which the last <code>Fiber.yield</code>
- * was called, or starts running it if it is the first call to
- * <code>resume</code>. Arguments passed to resume will be the value of
- * the <code>Fiber.yield</code> expression or will be passed as block
- * parameters to the fiber's block if this is the first <code>resume</code>.
- *
- * Alternatively, when resume is called it evaluates to the arguments passed
- * to the next <code>Fiber.yield</code> statement inside the fiber's block
- * or to the block value if it runs to completion without any
- * <code>Fiber.yield</code>
- */
-static mrb_value
-fiber_resume(mrb_state *mrb, mrb_value self)
-{
- mrb_value *a;
- mrb_int len;
- mrb_bool vmexec = FALSE;
-
- mrb_get_args(mrb, "*!", &a, &len);
- if (mrb->c->ci->acc < 0) {
- vmexec = TRUE;
- }
- return fiber_switch(mrb, self, len, a, TRUE, vmexec);
-}
-
-/* resume thread with given arguments */
-MRB_API mrb_value
-mrb_fiber_resume(mrb_state *mrb, mrb_value fib, mrb_int len, const mrb_value *a)
-{
- return fiber_switch(mrb, fib, len, a, TRUE, TRUE);
-}
-
-/*
- * call-seq:
- * fiber.alive? -> true or false
- *
- * Returns true if the fiber can still be resumed. After finishing
- * execution of the fiber block this method will always return false.
- */
-static mrb_value
-fiber_alive_p(mrb_state *mrb, mrb_value self)
-{
- struct mrb_context *c = fiber_check(mrb, self);
- return mrb_bool_value(c->status != MRB_FIBER_TERMINATED);
-}
-
-static mrb_value
-fiber_eq(mrb_state *mrb, mrb_value self)
-{
- mrb_value other;
- mrb_get_args(mrb, "o", &other);
-
- if (mrb_type(other) != MRB_TT_FIBER) {
- return mrb_false_value();
- }
- return mrb_bool_value(fiber_ptr(self) == fiber_ptr(other));
-}
-
-/*
- * call-seq:
- * fiber.transfer(args, ...) -> obj
- *
- * Transfers control to receiver fiber of the method call.
- * Unlike <code>resume</code> the receiver wouldn't be pushed to call
- * stack of fibers. Instead it will switch to the call stack of
- * transferring fiber.
- * When resuming a fiber that was transferred to another fiber it would
- * cause double resume error. Though when the fiber is re-transferred
- * and <code>Fiber.yield</code> is called, the fiber would be resumable.
- */
-static mrb_value
-fiber_transfer(mrb_state *mrb, mrb_value self)
-{
- struct mrb_context *c = fiber_check(mrb, self);
- mrb_value* a;
- mrb_int len;
-
- fiber_check_cfunc(mrb, mrb->c);
- mrb_get_args(mrb, "*!", &a, &len);
-
- if (c == mrb->root_c) {
- mrb->c->status = MRB_FIBER_TRANSFERRED;
- fiber_switch_context(mrb, c);
- MARK_CONTEXT_MODIFY(c);
- return fiber_result(mrb, a, len);
- }
-
- if (c == mrb->c) {
- return fiber_result(mrb, a, len);
- }
-
- return fiber_switch(mrb, self, len, a, FALSE, FALSE);
-}
-
-/* yield values to the caller fiber */
-/* mrb_fiber_yield() must be called as `return mrb_fiber_yield(...)` */
-MRB_API mrb_value
-mrb_fiber_yield(mrb_state *mrb, mrb_int len, const mrb_value *a)
-{
- struct mrb_context *c = mrb->c;
-
- if (!c->prev) {
- mrb_raise(mrb, E_FIBER_ERROR, "can't yield from root fiber");
- }
-
- fiber_check_cfunc(mrb, c);
- c->prev->status = MRB_FIBER_RUNNING;
- c->status = MRB_FIBER_SUSPENDED;
- fiber_switch_context(mrb, c->prev);
- c->prev = NULL;
- if (c->vmexec) {
- c->vmexec = FALSE;
- mrb->c->ci->acc = CI_ACC_RESUMED;
- }
- MARK_CONTEXT_MODIFY(mrb->c);
- return fiber_result(mrb, a, len);
-}
-
-/*
- * call-seq:
- * Fiber.yield(args, ...) -> obj
- *
- * Yields control back to the context that resumed the fiber, passing
- * along any arguments that were passed to it. The fiber will resume
- * processing at this point when <code>resume</code> is called next.
- * Any arguments passed to the next <code>resume</code> will be the
- *
- * mruby limitation: Fiber resume/yield cannot cross C function boundary.
- * thus you cannot yield from #initialize which is called by mrb_funcall().
- */
-static mrb_value
-fiber_yield(mrb_state *mrb, mrb_value self)
-{
- mrb_value *a;
- mrb_int len;
-
- mrb_get_args(mrb, "*!", &a, &len);
- return mrb_fiber_yield(mrb, len, a);
-}
-
-/*
- * call-seq:
- * Fiber.current() -> fiber
- *
- * Returns the current fiber. If you are not running in the context of
- * a fiber this method will return the root fiber.
- */
-static mrb_value
-fiber_current(mrb_state *mrb, mrb_value self)
-{
- if (!mrb->c->fib) {
- struct RFiber *f = (struct RFiber*)mrb_obj_alloc(mrb, MRB_TT_FIBER, mrb_class_ptr(self));
-
- f->cxt = mrb->c;
- mrb->c->fib = f;
- }
- return mrb_obj_value(mrb->c->fib);
-}
-
-void
-mrb_mruby_fiber_gem_init(mrb_state* mrb)
-{
- struct RClass *c;
-
- c = mrb_define_class(mrb, "Fiber", mrb->object_class);
- MRB_SET_INSTANCE_TT(c, MRB_TT_FIBER);
-
- mrb_define_method(mrb, c, "initialize", fiber_init, MRB_ARGS_NONE());
- mrb_define_method(mrb, c, "resume", fiber_resume, MRB_ARGS_ANY());
- mrb_define_method(mrb, c, "transfer", fiber_transfer, MRB_ARGS_ANY());
- mrb_define_method(mrb, c, "alive?", fiber_alive_p, MRB_ARGS_NONE());
- mrb_define_method(mrb, c, "==", fiber_eq, MRB_ARGS_REQ(1));
-
- mrb_define_class_method(mrb, c, "yield", fiber_yield, MRB_ARGS_ANY());
- mrb_define_class_method(mrb, c, "current", fiber_current, MRB_ARGS_NONE());
-
- mrb_define_class(mrb, "FiberError", mrb->eStandardError_class);
-}
-
-void
-mrb_mruby_fiber_gem_final(mrb_state* mrb)
-{
-}