Exemplo n.º 1
0
static struct mrb_context*
fiber_check(mrb_state *mrb, mrb_value fib)
{
  struct RFiber *f = (struct RFiber*)mrb_ptr(fib);

  if (!f->cxt) {
    mrb_raise(mrb, E_ARGUMENT_ERROR, "uninitialized Fiber");
  }
  return f->cxt;
}
Exemplo n.º 2
0
mrb_bool
mrb_obj_eq(mrb_state *mrb, mrb_value v1, mrb_value v2)
{
  if (mrb_type(v1) != mrb_type(v2)) return FALSE;
  switch (mrb_type(v1)) {
  case MRB_TT_TRUE:
    return TRUE;

  case MRB_TT_FALSE:
  case MRB_TT_FIXNUM:
    return (v1.value.i == v2.value.i);
  case MRB_TT_SYMBOL:
    return (v1.value.sym == v2.value.sym);

  case MRB_TT_FLOAT:
    return (mrb_float(v1) == mrb_float(v2));

  default:
    return (mrb_ptr(v1) == mrb_ptr(v2));
  }
}
Exemplo n.º 3
0
/*
 *  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 (RuntimeError)
 *
 *  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 (RuntimeError)
 *
 */
static mrb_value
fiber_init(mrb_state *mrb, mrb_value self)
{
  static const struct mrb_context mrb_context_zero = { 0 };
  struct RFiber *f = (struct RFiber*)mrb_ptr(self);
  struct mrb_context *c;
  struct RProc *p;
  mrb_callinfo *ci;
  mrb_value blk;

  mrb_get_args(mrb, "&", &blk);
  
  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_ARGUMENT_ERROR, "tried to create Fiber from C defined method");
  }

  f->cxt = (struct mrb_context*)mrb_malloc(mrb, sizeof(struct mrb_context));
  *f->cxt = mrb_context_zero;
  c = f->cxt;

  /* initialize VM stack */
  c->stbase = (mrb_value *)mrb_calloc(mrb, FIBER_STACK_INIT_SIZE, sizeof(mrb_value));
  c->stend = c->stbase + FIBER_STACK_INIT_SIZE;
  c->stack = c->stbase;

  /* 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;
  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;
}
Exemplo n.º 4
0
inline bool operator==(mrb_value v1, mrb_value v2)
{
	if (mrb_type(v1) != mrb_type(v2))
		return false;

	switch (mrb_type(v1))
	{
	case MRB_TT_TRUE:
		return true;

	case MRB_TT_FALSE:
	case MRB_TT_FIXNUM:
		return (v1.value.i == v2.value.i);
	case MRB_TT_SYMBOL:
		return (v1.value.sym == v2.value.sym);

	case MRB_TT_FLOAT:
		return (mrb_float(v1) == mrb_float(v2));

	default:
		return (mrb_ptr(v1) == mrb_ptr(v2));
	}
}
Exemplo n.º 5
0
static mrb_value
mrb_uv_key_set(mrb_state *mrb, mrb_value self)
{
  uv_key_t *key;
  void *p;
  mrb_value new_val;
  mrb_value ary;

  mrb_get_args(mrb, "o", &new_val);

  if (mrb_type(new_val) < MRB_TT_HAS_BASIC) {
    mrb_raisef(mrb, E_TYPE_ERROR, "cannot store value without basic: %S", new_val);
  }

  key = (uv_key_t*)mrb_uv_get_ptr(mrb, self, &mrb_uv_key_type);
  p = uv_key_get(key);

  ary = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "values"));
  mrb_assert(mrb_array_p(ary));

  if (p) {
    /* remove value */
    int i, dst;
    for (i = 0, dst = 0; i < RARRAY_LEN(ary); ++i) {
      mrb_value v = RARRAY_PTR(ary)[i];
      if (mrb_ptr(v) != p) {
        mrb_ary_ptr(ary)->ptr[dst++] = v;
      }
    }
    RARRAY_LEN(ary) = dst;
  }

  uv_key_set(key, mrb_ptr(new_val));
  mrb_ary_push(mrb, ary, new_val); /* protect from GC */

  return new_val;
}