예제 #1
0
mrb_value
cfunc_rubyvm_task_wait(mrb_state *mrb, mrb_value self)
{
    struct queue_task *task = DATA_PTR(self);
    if(task->status == queue_task_queued || task->status == queue_task_running) {
        pthread_mutex_lock(&task->sync_mutex);
        pthread_cond_wait(&task->sync_cond, &task->sync_mutex);
        pthread_mutex_unlock(&task->sync_mutex);
    }

    return task_arg_to_mrb_value(mrb, task->result);
}
예제 #2
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;
}
예제 #3
0
mrb_value task_arg_to_mrb_value(mrb_state *mrb, struct task_arg* arg)
{
    mrb_value v;

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

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

    case MRB_TT_SYMBOL:
        v.value.sym = mrb_intern(mrb, arg->value.string.ptr);
        break;

    case MRB_TT_STRING:
        v = mrb_str_new(mrb, arg->value.string.ptr, arg->value.string.len);
        break;

    case MRB_TT_ARRAY:
        {
            v = mrb_ary_new_capa(mrb, arg->value.array.len);
            struct RArray *ary = mrb_ary_ptr(v);
            ary->len = arg->value.array.len;
            int i;
            for(i=0; i<arg->value.array.len; i++) {
                ary->ptr[i] = task_arg_to_mrb_value(mrb, arg->value.array.ptr[i]);
            }
        }
        break;

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

    return v;
}
예제 #4
0
mrb_value
cfunc_rubyvm_task_result(mrb_state *mrb, mrb_value self)
{
    struct queue_task *task = DATA_PTR(self);
    return task_arg_to_mrb_value(mrb, task->result);
}