読者です 読者をやめる 読者になる 読者になる

module Eventがわからない…

ocaml

Railsでカミさん用に作ったiKnowモドキも仕様変更の嵐が収まってきて、OSの入れ替えなんかも終わったので、久しぶりにOCamlをいじってみようと思ったのですが、Std Libを見てたらEventというmoduleがあることに気がついた。

ちらっと説明(和訳)を見てみると…

val sync : 'a event -> 'a

イベントを「同期」させます。すなわちイベントで指定された
すべての外部世界への可能な通信を行い、通信のうちひとつが成功するまでブロックします。
通信の返り値を返します。

全然わからん。

で、ぐぐってみたところ2chの過去スレ()で、とても良い説明があった。

252 :デフォルトの名無しさん:2006/02/20(月) 14:21:50
    >>233
    OCaml でマルチスレッドなプログラムを作る場合、二通りのスタイルがある。

    1) Thread,Mutex,Conditionモジュールを駆使して、従来の pthread ライブラ
    リを叩くような感覚で事を進めるスタイル。pthread を使った事がある人
    やマルチスレッドプログラミングをかじった事がある人は難なく使える。
    ディープな人には物足りない。

    2) Thread,Eventモジュールを駆使してお気楽にマルチスレッドを扱える、
    concurrent プログラミングと呼ばれるスタイル。concurrent プログラミ
    ングに初挑戦の場合、最初は意味が分からない。でも、分かってくれば便
    利。基本的に一対多の同期はできないので、やっぱりディープな人には物
    足りない。

    どちらかというと、2)をお薦め。せっかくOCamlでやるのだから。


253 :デフォルトの名無しさん:2006/02/20(月) 14:32:48
    例題として、二つの計算を別スレッドで立ち上げて、それらの計算結果を表示
    するプログラムを作ってみよう。

    open Event

    let compute_mul ch = sync (send ch (7 * 8))
    let compute_add ch = sync (send ch (7 + 8))

    let _ =
    let mul_ch = new_channel () in
    let add_ch = new_channel () in
    ignore (Thread.create compute_mul mul_ch);
    ignore (Thread.create compute_add add_ch);
    Printf.printf "mul %d\n" (sync (receive mul_ch));
    Printf.printf "add %d\n" (sync (receive add_ch))

    これを th.ml として保存しコンパイル。

    $ocamlc -thread -o test unix.cma threads.cma th.ml
    $./test
    mul 56
    add 15

    となるはず。これができれば第一歩ですな。



254 :デフォルトの名無しさん:2006/02/20(月) 14:42:30
    同じ事だけど、こっちの方がいいかも。スレッドを作って、それへのチャネル
    を返すというスタイルが基本。

    open Event

    let compute_mul () =
    let ch = new_channel () in
    ignore (Thread.create (fun () -> sync (send ch (7 * 8))) ());
    ch

    let compute_add () =
    let ch = new_channel () in
    ignore (Thread.create (fun () -> sync (send ch (7 + 8))) ());
    ch

    let _ =
    let mul_ch = compute_mul () in
    let add_ch = compute_add () in
    Printf.printf "mul %d\n" (sync (receive mul_ch));
    Printf.printf "add %d\n" (sync (receive add_ch))

まぁ、ぱっと見、コードはよくわからん。なので、考えてみます。


253のコードについて

  • compute_mulは受け取ったchannelを通して(7 * 8)を送る。その通信が成功するまでブロック。compute_addも同様。
  • (mul|add)_chというchannelを作って、別スレッドにてcompute_(mul|add)に渡してあげる。そうすると、(mul|add)_chに(7 * 8)とかを送ろうとするであろう。
  • で、(mul|add)_chからrecieveできるまでブロッキングする、と。
  • send, recieveはchannel経由での送受信を行い、それらが戻すeventをsyncが捕まえてブロックする、ということか。


254のコードについて

  • 253とやっていることは一緒。そもそも「同じ事だけど」って書いてあるし…
  • 結局なにがうれしいのかというと、channelを通して送受信することで、コードがシンプルになるってこと?Mutexとかが無くなるし。


こりはおもしろい… オラ、ワクワクしてきたぞ。

っていうか何このスレ?

255以降も素晴らしくなっているぞ。自然と議論が活発となっていき、有意義な講義が展開されておる…

2ch関数型言語MLスレ…要チェックや!と思ったらPart5で止まっていたか…まぁ、いいや。