예제 #1
0
파일: fiber.c 프로젝트: ASnow/mruby
/*
 *  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;
    mrb->c = c;
    c->status = MRB_FIBER_RUNNING;
    MARK_CONTEXT_MODIFY(c);
    mrb_write_barrier(mrb, (struct RBasic*)c->fib);
    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);
}
예제 #2
0
파일: Fiber.cpp 프로젝트: ga2arch/fibers
bool Fiber::yield() {
    Fiber *f = current;
    for (auto *p = ++f ;; f++) {
        if (p == &fibers.at(MAXFIBERS-1)) {
            p = &fibers.at(0);

        } else if (p->status == Fiber::Ready) {
            f = p;
            break;
        }
        else if (p == f) {
            return false;
        }
    }

    if (current->status != Fiber::Unused) {
        current->status = Fiber::Ready;
    }

    f->status = Fiber::Running;
    auto old_ctx = &current->context;
    auto new_ctx = &f->context;

    current = f;
    fiber_switch(old_ctx, new_ctx);
    return true;
}
예제 #3
0
파일: fiber.c 프로젝트: Synposis/mruby
/*
 *  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;
  int len;
  mrb_get_args(mrb, "*", &a, &len);
  return fiber_switch(mrb, self, len, a, TRUE);
}
예제 #4
0
VALUE
rb_fiber_resume(VALUE fibval, int argc, VALUE *argv)
{
    rb_fiber_t *fib;
    GetFiberPtr(fibval, fib);

    if (fib->prev != Qnil) {
	rb_raise(rb_eFiberError, "double resume");
    }

    return fiber_switch(fibval, argc, argv, 1);
}
예제 #5
0
파일: cont.c 프로젝트: genki/ruby
VALUE
rb_fiber_resume(VALUE fib, int argc, VALUE *argv)
{
    rb_context_t *cont;
    GetContPtr(fib, cont);

    if (cont->prev != Qnil) {
	rb_raise(rb_eFiberError, "double resume");
    }

    return fiber_switch(fib, argc, argv, 1);
}
예제 #6
0
파일: fiber.c 프로젝트: ASnow/mruby
/*
 *  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);
}
예제 #7
0
파일: fiber.c 프로젝트: ASnow/mruby
/* 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);
}
예제 #8
0
VALUE
rb_fiber_transfer(VALUE fib, int argc, VALUE *argv)
{
    return fiber_switch(fib, argc, argv, 0);
}