diff options
Diffstat (limited to 'web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-fiber')
3 files changed, 0 insertions, 633 deletions
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-fiber/mrbgem.rake b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-fiber/mrbgem.rake deleted file mode 100644 index 815cd3c4b..000000000 --- a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-fiber/mrbgem.rake +++ /dev/null @@ -1,5 +0,0 @@ -MRuby::Gem::Specification.new('mruby-fiber') do |spec| - spec.license = 'MIT' - spec.author = 'mruby developers' - spec.summary = 'Fiber class' -end 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) -{ -} diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-fiber/test/fiber.rb b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-fiber/test/fiber.rb deleted file mode 100644 index d063a0a62..000000000 --- a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-fiber/test/fiber.rb +++ /dev/null @@ -1,208 +0,0 @@ -assert('Fiber.new') do - f = Fiber.new{} - assert_kind_of Fiber, f -end - -assert('Fiber#resume') do - f = Fiber.new{|x| x } - assert_equal 2, f.resume(2) -end - -assert('Fiber#transfer') do - f2 = nil - f1 = Fiber.new do |v| - Fiber.yield v - f2.transfer - end - f2 = Fiber.new do - f1.transfer(1) - f1.transfer(1) - Fiber.yield 2 - end - assert_equal 1, f2.resume - assert_raise(FiberError) { f2.resume } - assert_equal 2, f2.transfer - assert_raise(FiberError) { f1.resume } - f1.transfer - f2.resume - assert_false f1.alive? - assert_false f2.alive? -end - -assert('Fiber#alive?') do - f = Fiber.new{ Fiber.yield } - f.resume - assert_true f.alive? - f.resume - assert_false f.alive? -end - -assert('Fiber#==') do - root = Fiber.current - assert_equal root, root - assert_equal root, Fiber.current - assert_false root != Fiber.current - f = Fiber.new { - assert_false root == Fiber.current - } - f.resume - assert_false f == root - assert_true f != root -end - -assert('Fiber.yield') do - f = Fiber.new{|x| Fiber.yield x } - assert_equal 3, f.resume(3) - assert_true f.alive? -end - -assert('FiberError') do - assert_equal StandardError, FiberError.superclass -end - -assert('Fiber iteration') do - f1 = Fiber.new{ - [1,2,3].each{|x| Fiber.yield(x)} - } - f2 = Fiber.new{ - [9,8,7].each{|x| Fiber.yield(x)} - } - a = [] - 3.times { - a << f1.resume - a << f2.resume - } - assert_equal [1,9,2,8,3,7], a -end - -assert('Fiber with splat in the block argument list') { - Fiber.new{|*x|x}.resume(1) == [1] -} - -assert('Fiber raises on resume when dead') do - assert_raise(FiberError) do - f = Fiber.new{} - f.resume - assert_false f.alive? - f.resume - end -end - -assert('Yield raises when called on root fiber') do - assert_raise(FiberError) { Fiber.yield } -end - -assert('Double resume of Fiber') do - f1 = Fiber.new {} - f2 = Fiber.new { - f1.resume - assert_raise(FiberError) { f2.resume } - Fiber.yield 0 - } - assert_equal 0, f2.resume - f2.resume - assert_false f1.alive? - assert_false f2.alive? -end - -assert('Recursive resume of Fiber') do - f1, f2 = nil, nil - f1 = Fiber.new { assert_raise(FiberError) { f2.resume } } - f2 = Fiber.new { - f1.resume - Fiber.yield 0 - } - f3 = Fiber.new { - f2.resume - } - assert_equal 0, f3.resume - f2.resume - assert_false f1.alive? - assert_false f2.alive? - assert_false f3.alive? -end - -assert('Root fiber resume') do - root = Fiber.current - assert_raise(FiberError) { root.resume } - f = Fiber.new { - assert_raise(FiberError) { root.resume } - } - f.resume - assert_false f.alive? -end - -assert('Fiber without block') do - assert_raise(ArgumentError) { Fiber.new } -end - - -assert('Transfer to self.') do - result = [] - f = Fiber.new { result << :start; f.transfer; result << :end } - f.transfer - assert_equal [:start, :end], result - - result = [] - f = Fiber.new { result << :start; f.transfer; result << :end } - f.resume - assert_equal [:start, :end], result -end - -assert('Resume transferred fiber') do - f = Fiber.new { - assert_raise(FiberError) { f.resume } - } - f.transfer -end - -assert('Root fiber transfer.') do - result = nil - root = Fiber.current - f = Fiber.new { - result = :ok - root.transfer - } - f.resume - assert_true f.alive? - assert_equal :ok, result -end - -assert('Break nested fiber with root fiber transfer') do - root = Fiber.current - - result = nil - f2 = nil - f1 = Fiber.new { - Fiber.yield f2.resume - result = :f1 - } - f2 = Fiber.new { - result = :to_root - root.transfer :from_f2 - result = :f2 - } - assert_equal :from_f2, f1.resume - assert_equal :to_root, result - assert_equal :f2, f2.transfer - assert_equal :f2, result - assert_false f2.alive? - assert_equal :f1, f1.resume - assert_equal :f1, result - assert_false f1.alive? -end - -assert('CRuby Fiber#transfer test.') do - ary = [] - f2 = nil - f1 = Fiber.new{ - ary << f2.transfer(:foo) - :ok - } - f2 = Fiber.new{ - ary << f1.transfer(:baz) - :ng - } - assert_equal :ok, f1.transfer - assert_equal [:baz], ary -end |