ひとり勉強会

ひとり楽しく勉強会

Init_yarvcore @ yarvcore.c

この関数は、基本的には、YARVRubyスクリプトからさわれるようにするための、Rubyライブラリを提供するものです。

    mYarvCore = rb_define_module("YARVCore");
    rb_define_const(mYarvCore, "VERSION",
                    rb_str_new2(yarv_version));
    ... 略 ...

こんなのが延々と続いています。YARVRubyから操作する方法には今のところ興味がないので、この辺りはさらっと読み飛ばしちゃえ〜!と思いきや、さりげなく

    idAnswer = rb_intern(
      "the_answer_to_life_the_universe_and_everything");

こんなのが混じってて面白かったです。

それはともかく、ライブラリの提供と思ってたら、途中で

    // make vm
    /* create main thread */

のようなコメントがでてきはじめて戸惑いました。さっきvmやthreadは作らなかった??

念のため、make vm以降をちゃんと見てみました。

    /* create vm object */
    VALUE vmval = vm_alloc(cYarvVM);
    yarv_vm_t *vm;
    yarv_thread_t *th;
    vm = theYarvVM;

    xfree(RDATA(vmval)->data);
    RDATA(vmval)->data = vm;
    vm->self = vmval;

vm_alloc(cYarvVM) で、RubyのYarvVMクラスのインスタンス、vmvalを作っています。そこに、さっき作ったtheYarvVMをセットしたり、逆にtheYarvVMにvmvalをセットしたりしていますね。つまり、さっき作ったtheYarvVMは、YARV内部で使う仮想マシンの表現です。ここで作るvmvalは、それをRubyスクリプトに見せるためのラッパーオブジェクトみたいなのということでしょう。「vmを意味する(Rubyでの)オブジェクトを作る」処理。

続いて、create main thread というコメントの箇所です

    /* create main thread */
    vm->main_thread_val = yarv_thread_alloc(cYarvThread);
    GetThreadPtr(vm->main_thread_val, th);

    vm->main_thread = th;
    vm->running_thread = th;
    GET_THREAD()->vm = vm;
    thread_free(GET_THREAD());
    th->vm = vm;
    yarv_set_current_running_thread(th);

同じように、yarv_thread_alloc(cYarvThread) でYarvThreadクラスのインスタンスを作っています。しかしここで、姉さん、事件です!

  • yarv_thread_alloc
    • thread_alloc
    • thread_init
      • th_init

yarv_thread_allocの中では、またth_initで新しくスレッドを表す構造を作っています。そのうしろでは、さっき作ったスレッドGET_THREAD()をthread_freeで解放して、今新しく作ったスレッドを yarv_set_current_running_thread で再設定しているように見えます。

ううむ、なんででしょう。

  • Init_yarvcoreは繰り返し呼ばれる可能性があって、呼ばれた時点で前のスレッドは破棄するという動作になっている

というのはありそうですし、納得がいきます。でもそうすると、Init_yarvで一度スレッドを作ってるのはなんでだろ?ちょっとまだわからないので、これは課題としてとっておきます。

とりあえずここでは、「YARVVMを表すRubyオブジェクトやスレッドを表すRubyオブジェクトを初期化して、組み込みオブジェクトとして提供している」ということで。