static mrb_value mrb_struct_initialize_withArg(mrb_state *mrb, int argc, mrb_value *argv, mrb_value self) { struct RClass *klass = mrb_obj_class(mrb, self); long n; struct RStruct *st; mrb_struct_modify(self); n = num_members(mrb, klass); if (n < argc) { mrb_raise(mrb, E_ARGUMENT_ERROR, "struct size differs"); } st = RSTRUCT(self); st->ptr = mrb_calloc(mrb, sizeof(mrb_value), n); st->len = n; memcpy(st->ptr, argv, sizeof(mrb_value)*argc); return self; }
void mrb_init_proc(mrb_state *mrb) { struct RProc *m; mrb_code *call_iseq = mrb_malloc(mrb, sizeof(mrb_code)); mrb_irep *call_irep = mrb_calloc(mrb, sizeof(mrb_irep), 1); if ( call_iseq == NULL || call_irep == NULL ) return; *call_iseq = MKOP_A(OP_CALL, 0); call_irep->idx = -1; call_irep->flags = MRB_IREP_NOFREE; call_irep->iseq = call_iseq; call_irep->ilen = 1; mrb->proc_class = mrb_define_class(mrb, "Proc", mrb->object_class); m = mrb_proc_new(mrb, call_irep); mrb_define_method_raw(mrb, mrb->proc_class, mrb_intern(mrb, "call"), m); mrb_define_method_raw(mrb, mrb->proc_class, mrb_intern(mrb, "[]"), m); }
/* * 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 (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"); } f->cxt = (struct mrb_context*)mrb_malloc(mrb, sizeof(struct mrb_context)); *f->cxt = mrb_context_zero; c = f->cxt; /* 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; 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 mrb_value mrb_future_init(mrb_state *oldmrb, mrb_value self) { static const struct mrb_context mrb_context_zero = { 0 }; mrb_state *mrb = mrb_open(); mrb_future_context *context = (mrb_future_context *) malloc(sizeof(mrb_future_context)); struct mrb_context *c; struct RProc *p; mrb_callinfo *ci; mrb_value blk; size_t slen; int argc; mrb_value* argv; *mrb = *oldmrb; mrb_get_args(mrb, "*&", &argv, &argc, &blk); p = mrb_proc_ptr(blk); c = (struct mrb_context*)mrb_malloc(mrb, sizeof(struct mrb_context)); *c = mrb_context_zero; mrb->c = c; context->mrb = mrb; context->oldmrb = oldmrb; context->proc = mrb_proc_ptr(blk); context->argc = argc; context->argv = argv; context->self = self; /* initialize VM stack */ slen = FIBER_STACK_INIT_SIZE; if (!MRB_PROC_CFUNC_P(p) && 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 future object(self) from a block */ c->stack[0] = self; /* 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; if (!MRB_PROC_CFUNC_P(p)) { ci->pc = p->body.irep->iseq; ci->nregs = p->body.irep->nregs; } ci[1] = ci[0]; c->ci++; /* push dummy callinfo */ mrb_iv_set(oldmrb, self, mrb_intern_cstr(oldmrb, "_context"), mrb_cptr_value(oldmrb, context)); mrb_iv_set(oldmrb, self, mrb_intern_cstr(oldmrb, "_state"), mrb_fixnum_value(FUTURE_RUNNING)); pthread_create(&context->thread, NULL, &mrb_future_func, (void *)context); return self; }