Beispiel #1
0
static mrb_value
mrb_thread_init(mrb_state* mrb, mrb_value self) {
  mrb_value proc = mrb_nil_value();
  mrb_int argc;
  mrb_value* argv;
  mrb_get_args(mrb, "&*", &proc, &argv, &argc);
  if (!mrb_nil_p(proc) && MRB_PROC_CFUNC_P(mrb_proc_ptr(proc))) {
    mrb_raise(mrb, E_RUNTIME_ERROR, "forking C defined block");
  }
  if (!mrb_nil_p(proc)) {
    int i, l;
    mrb_thread_context* context = (mrb_thread_context*) malloc(sizeof(mrb_thread_context));
    context->mrb_caller = mrb;
    context->mrb = mrb_open_allocf(mrb->allocf, mrb->allocf_ud);
    migrate_all_symbols(mrb, context->mrb);
    context->proc = mrb_proc_new(mrb, mrb_proc_ptr(proc)->body.irep);
    context->proc->target_class = context->mrb->object_class;
    context->argc = argc;
    context->argv = calloc(sizeof (mrb_value), context->argc);
    context->result = mrb_nil_value();
    context->alive = TRUE;
    for (i = 0; i < context->argc; i++) {
      context->argv[i] = migrate_simple_value(mrb, argv[i], context->mrb);
    }

    {
      mrb_value gv = mrb_funcall(mrb, self, "global_variables", 0, NULL);
      l = RARRAY_LEN(gv);
      for (i = 0; i < l; i++) {
        mrb_int len;
        int ai = mrb_gc_arena_save(mrb);
        mrb_value k = mrb_ary_entry(gv, i);
        mrb_value o = mrb_gv_get(mrb, mrb_symbol(k));
        if (is_safe_migratable_simple_value(mrb, o, context->mrb)) {
          const char *p = mrb_sym2name_len(mrb, mrb_symbol(k), &len);
          mrb_gv_set(context->mrb,
            mrb_intern_static(context->mrb, p, len),
            migrate_simple_value(mrb, o, context->mrb));
        }
        mrb_gc_arena_restore(mrb, ai);
      }
    }

    mrb_iv_set(mrb, self, mrb_intern_lit(mrb, "context"), mrb_obj_value(
      Data_Wrap_Struct(mrb, mrb->object_class,
      &mrb_thread_context_type, (void*) context)));

    pthread_create(&context->thread, NULL, &mrb_thread_func, (void*) context);
  }
  return self;
}
Beispiel #2
0
static mrb_value
mrb_thread_init(mrb_state* mrb, mrb_value self) {
  mrb_value proc = mrb_nil_value();
  int argc;
  mrb_value* argv;
  mrb_get_args(mrb, "&*", &proc, &argv, &argc);
  if (!mrb_nil_p(proc)) {
    int i;
    mrb_thread_context* context = (mrb_thread_context*) malloc(sizeof(mrb_thread_context));
    context->mrb_caller = mrb;
    context->mrb = mrb_open();
    context->proc = mrb_proc_ptr(proc);
    context->argc = argc;
    context->argv = argv;
    context->argv = calloc(sizeof (mrb_value), context->argc);
    context->result = mrb_nil_value();
    for (i = 0; i < context->argc; i++) {
      context->argv[i] = migrate_simple_value(mrb, argv[i], context->mrb);
    }

    mrb_iv_set(mrb, self, mrb_intern_cstr(mrb, "context"), mrb_obj_value(
      Data_Wrap_Struct(mrb, mrb->object_class,
      &mrb_thread_context_type, (void*) context)));

    pthread_create(&context->thread, NULL, &mrb_thread_func, (void*) context);
  }
  return self;
}
Beispiel #3
0
static mrb_value
mrb_thread_join(mrb_state* mrb, mrb_value self) {
  mrb_value value_context = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "context"));
  mrb_thread_context* context = NULL;
  Data_Get_Struct(mrb, value_context, &mrb_thread_context_type, context);
  pthread_join(context->thread, NULL);

  context->result = migrate_simple_value(mrb, context->result, mrb);
  mrb_close(context->mrb);
  context->mrb = NULL;
  return context->result;
}
Beispiel #4
0
static mrb_value
mrb_queue_unshift(mrb_state* mrb, mrb_value self) {
  mrb_value arg;
  mrb_queue_context* context = DATA_PTR(self);
  mrb_queue_lock(mrb, self);
  mrb_get_args(mrb, "o", &arg);
  mrb_ary_unshift(context->mrb, context->queue, migrate_simple_value(mrb, arg, context->mrb));
  mrb_queue_unlock(mrb, self);
  if (pthread_mutex_unlock(&context->queue_lock) != 0) {
    mrb_raise(mrb, E_RUNTIME_ERROR, "cannot unlock");
  }
  return mrb_nil_value();
}
Beispiel #5
0
static void
migrate_simple_iv(mrb_state *mrb, mrb_value v, mrb_state *mrb2, mrb_value v2)
{
  mrb_value ivars = mrb_obj_instance_variables(mrb, v);
  struct RArray *a = mrb_ary_ptr(ivars);
  mrb_value iv;
  mrb_int i;

  for (i=0; i<a->len; i++) {
    mrb_sym sym = mrb_symbol(a->ptr[i]);
    mrb_sym sym2 = migrate_sym(mrb, sym, mrb2);
    iv = mrb_iv_get(mrb, v, sym);
    mrb_iv_set(mrb2, v2, sym2, migrate_simple_value(mrb, iv, mrb2));
  }
}
Beispiel #6
0
static mrb_value
mrb_queue_shift(mrb_state* mrb, mrb_value self) {
  mrb_value ret;
  mrb_queue_context* context = DATA_PTR(self);
  int len;
  mrb_queue_lock(mrb, self);
  len = RARRAY_LEN(context->queue);
  mrb_queue_unlock(mrb, self);
  if (len == 0) {
    if (pthread_mutex_lock(&context->queue_lock) != 0) {
      mrb_raise(mrb, E_RUNTIME_ERROR, "cannot lock");
    }
  }
  mrb_queue_lock(mrb, self);
  ret = migrate_simple_value(context->mrb, mrb_ary_shift(context->mrb, context->queue), mrb);
  mrb_queue_unlock(mrb, self);
  return ret;
}
Beispiel #7
0
// based on https://gist.github.com/3066997
static mrb_value
migrate_simple_value(mrb_state *mrb, mrb_value v, mrb_state *mrb2) {
  mrb_value nv;

  switch (mrb_type(v)) {
  case MRB_TT_OBJECT:
  case MRB_TT_EXCEPTION:
    {
      struct RObject *o = mrb_obj_ptr(v);
      mrb_value path = mrb_class_path(mrb, o->c);
      struct RClass *c;

      if (mrb_nil_p(path)) {
        mrb_raise(mrb, E_TYPE_ERROR, "cannot migrate class");
      }
      c = mrb_class_get(mrb2, RSTRING_PTR(path));
      nv = mrb_obj_value(mrb_obj_alloc(mrb2, mrb_type(v), c));
    }
    migrate_simple_iv(mrb, v, mrb2, nv);
    break;
  case MRB_TT_FALSE:
  case MRB_TT_TRUE:
  case MRB_TT_FIXNUM:
    nv = v;
    break;
  case MRB_TT_SYMBOL:
    nv = mrb_symbol_value(migrate_sym(mrb, mrb_symbol(v), mrb2));
    break;
  case MRB_TT_FLOAT:
    nv = mrb_float_value(mrb2, mrb_float(v));
    break;
  case MRB_TT_STRING:
    nv = mrb_str_new(mrb2, RSTRING_PTR(v), RSTRING_LEN(v));
    break;
  case MRB_TT_RANGE:
    {
      struct RRange *r = mrb_range_ptr(v);
      nv = mrb_range_new(mrb2,
                         migrate_simple_value(mrb, r->edges->beg, mrb2),
                         migrate_simple_value(mrb, r->edges->end, mrb2),
                         r->excl);
    }
    break;
  case MRB_TT_ARRAY:
    {
      struct RArray *a0, *a1;
      int i;

      a0 = mrb_ary_ptr(v);
      nv = mrb_ary_new_capa(mrb2, a0->len);
      a1 = mrb_ary_ptr(nv);
      for (i=0; i<a0->len; i++) {
        int ai = mrb_gc_arena_save(mrb2);
        a1->ptr[i] = migrate_simple_value(mrb, a0->ptr[i], mrb2);
        a1->len++;
        mrb_gc_arena_restore(mrb2, ai);
      }
    }
    break;
  case MRB_TT_HASH:
    {
      mrb_value ka;
      int i, l;

      nv = mrb_hash_new(mrb2);
      ka = mrb_hash_keys(mrb, v);
      l = RARRAY_LEN(ka);
      for (i = 0; i < l; i++) {
        int ai = mrb_gc_arena_save(mrb2);
        mrb_value k = migrate_simple_value(mrb, mrb_ary_entry(ka, i), mrb2);
        mrb_value o = migrate_simple_value(mrb, mrb_hash_get(mrb, v, k), mrb2);
        mrb_hash_set(mrb2, nv, k, o);
        mrb_gc_arena_restore(mrb2, ai);
      }
    }
    migrate_simple_iv(mrb, v, mrb2, nv);
    break;
  case MRB_TT_DATA:
    if (!is_safe_migratable_datatype(DATA_TYPE(v)))
      mrb_raise(mrb, E_TYPE_ERROR, "cannot migrate object");
    nv = v;
    DATA_PTR(nv) = DATA_PTR(v);
    DATA_TYPE(nv) = DATA_TYPE(v);
    migrate_simple_iv(mrb, v, mrb2, nv);
    break;
  default:
    mrb_raise(mrb, E_TYPE_ERROR, "cannot migrate object");
    break;
  }
  return nv;
}
Beispiel #8
0
// based on https://gist.github.com/3066997
static mrb_value
migrate_simple_value(mrb_state *mrb, mrb_value v, mrb_state *mrb2) {
  mrb_value nv = mrb_nil_value();

  nv.tt = v.tt;
  switch (mrb_type(v)) {
  case MRB_TT_OBJECT:
    nv.value.p = v.value.p;
    break;
  case MRB_TT_FALSE:
  case MRB_TT_TRUE:
  case MRB_TT_FIXNUM:
    nv.value.i = v.value.i;
    break;
  case MRB_TT_SYMBOL:
    nv = mrb_symbol_value(mrb_intern_str(mrb2, v));
    break;
  case MRB_TT_FLOAT:
    nv.value.f = v.value.f;
    break;
  case MRB_TT_STRING:
    nv = mrb_str_new(mrb2, RSTRING_PTR(v), RSTRING_LEN(v));
    break;
  case MRB_TT_ARRAY:
    {
      struct RArray *a0, *a1;
      int i;

      a0 = mrb_ary_ptr(v);
      nv = mrb_ary_new_capa(mrb2, a0->len);
      a1 = mrb_ary_ptr(nv);
      for (i=0; i<a0->len; i++) {
        int ai = mrb_gc_arena_save(mrb2);
        a1->ptr[i] = migrate_simple_value(mrb, a0->ptr[i], mrb2);
        a1->len++;
        mrb_gc_arena_restore(mrb2, ai);
      }
    }
    break;
  case MRB_TT_HASH:
    {
      mrb_value ka;
      int i, l;

      nv = mrb_hash_new(mrb2);
      ka = mrb_hash_keys(mrb, v);
      l = RARRAY_LEN(ka);
      for (i = 0; i < l; i++) {
        int ai = mrb_gc_arena_save(mrb2);
        mrb_value k = migrate_simple_value(mrb, mrb_ary_entry(ka, i), mrb2);
        mrb_value o = migrate_simple_value(mrb, mrb_hash_get(mrb, v, k), mrb2);
        mrb_hash_set(mrb2, nv, k, o);
        mrb_gc_arena_restore(mrb2, ai);
      }
    }
    break;
  default:
    mrb_raise(mrb, E_TYPE_ERROR, "cannot migrate object");
    break;
  }
  return nv;
}