Exemplo n.º 1
0
mrb_value
cfunc_rubyvm_dispatch(mrb_state *mrb, mrb_value self)
{
    struct cfunc_rubyvm_data *data = mrb_get_datatype(mrb, self, &cfunc_rubyvm_data_type);

    mrb_value name_obj, *args;
    int args_len;
    mrb_get_args(mrb, "o*", &name_obj, &args, &args_len);

    struct queue_task *task = malloc(sizeof(struct queue_task));
    task->refcount = 2;
    task->result = NULL;
    task->status = queue_task_queued;

    pthread_mutex_init(&task->sync_mutex, NULL);
    pthread_cond_init(&task->sync_cond, NULL);

    const char* name = mrb_string_value_ptr(mrb, name_obj);
    int name_len = strlen(name);
    task->name = malloc(name_len+1);
    strncpy(task->name, name, name_len+1);

    task->args_len = args_len;
    task->args = malloc(sizeof(struct task_arg) * task->args_len);
    for(int i=0; i<args_len; ++i) {
        task->args[i] = mrb_value_to_task_arg(mrb, args[i]);
    }

    pthread_mutex_lock(&data->queue_mutex);
    vector_enqueue(data->queue, task);
    pthread_cond_signal(&data->queue_cond);
    pthread_mutex_unlock(&data->queue_mutex);

    return mrb_obj_value((struct RObject *)Data_Wrap_Struct(mrb, cfunc_state(mrb)->rubyvm_task_class, &cfunc_rubyvm_task_data_type, task));
}
Exemplo n.º 2
0
struct task_arg* mrb_value_to_task_arg(mrb_state *mrb, mrb_value v)
{
    struct task_arg *arg = mrb_malloc(mrb, sizeof(struct task_arg));

    arg->tt = mrb_type(v);
    switch (mrb_type(v)) {
    case MRB_TT_FALSE:
    case MRB_TT_TRUE:
    case MRB_TT_FIXNUM:
        arg->value.i = v.value.i;
        break;

    case MRB_TT_FLOAT:
        arg->value.f = v.value.f;
        break;

    case MRB_TT_SYMBOL:
        {
            size_t len;
            const char* name = mrb_sym2name_len(mrb, v.value.sym, &len);
            arg->value.string.len = len;
            arg->value.string.ptr = mrb_malloc(mrb, len + 1);
            memcpy(arg->value.string.ptr, name, len + 1);
        }
        break;

    case MRB_TT_STRING:
        {
            struct RString *str = mrb_str_ptr(v);
            arg->value.string.len = str->len;
            arg->value.string.ptr = mrb_malloc(mrb, arg->value.string.len+1);
            memcpy(arg->value.string.ptr, str->ptr, arg->value.string.len+1);
        }
        break;

    case MRB_TT_ARRAY:
        {
            struct RArray *ary = mrb_ary_ptr(v);

            arg->value.array.len = ary->len;
            arg->value.array.ptr = mrb_malloc(mrb, ary->len * sizeof(struct task_arg));

            int i;
            for(i=0; i<ary->len; i++) {
                arg->value.array.ptr[i] = mrb_value_to_task_arg(mrb, ary->ptr[i]);
            }
        }
        break;

    default:
        mrb_free(mrb, arg);
        mrb_raise(mrb, E_TYPE_ERROR, "cannot pass to other RubyVM");
        break;
    }

    return arg;
}
Exemplo n.º 3
0
void*
cfunc_rubyvm_open(void *args)
{
    struct cfunc_rubyvm_data *data = args;
    mrb_state *mrb = mrb_open();
    data->state = mrb;
    
#ifdef DISABLE_GEMS
    init_cfunc_module(mrb);
#endif

    int n = mrb_read_irep(mrb, data->mrb_data);

    mrb_run(mrb, mrb_proc_new(mrb, mrb->irep[n]), mrb_top_self(mrb));

    if (mrb->exc) {
        return NULL;
    }

    while(true) {
        pthread_mutex_lock(&data->queue_mutex);

        while(data->queue->length == 0) {
            pthread_cond_wait(&data->queue_cond, &data->queue_mutex);
        }
        
        struct queue_task *task = vector_dequeue(data->queue);
        task->status = queue_task_running;
        mrb_sym taskname = mrb_intern(mrb, task->name);

        int args_len = task->args_len;
        mrb_value *args = mrb_malloc(mrb, sizeof(struct task_arg) * task->args_len);
        int i;
        for(i=0; i<task->args_len; ++i) {
            args[i] = task_arg_to_mrb_value(data->state, task->args[i]);
        }

        pthread_mutex_unlock(&data->queue_mutex);

        mrb_value result = mrb_funcall_argv(mrb, mrb_top_self(data->state), taskname, args_len, args);
        task->result = mrb_value_to_task_arg(mrb, result);
        task->status = queue_task_finished;
        pthread_cond_signal(&task->sync_cond);

        mrb_free(mrb, args);
        free_queue_task(mrb, task);
    }

    return NULL;
}