トップ
新規
単語検索
ヘルプ
OCamlテクニック/ivarの必要性
をテンプレートにして作成
開始行:
[[ivarの必要性]]
OCamlではCMLスタイルのスレッド間通信が可能です。
Eventモジュールには基本的なイベント型やその同期関数が揃っ...
ところが、ivarやmvarといった共有変数が無い為に苦しい状況...
#br
例えばとても単純に、整数を渡して計算結果を(今回は倍にし...
すぐに思いつくのは、次のようなコードです。
#br
let start_server () =
let in_ch, out_ch =
new_channel (), new_channel ()
in
let rec loop () =
let x = sync (receive in_ch) in
loop (sync (send out_ch (x * 2)))
in
ignore (Thread.create loop ());
in_ch, out_ch
let calc (in_ch, out_ch) x =
wrap (send in_ch x) (fun () -> sync (receive out_ch))
#br
これで全く問題ないです。
ただし、同期ポイントが要求を送るときになっている事に注目...
要求を送る時と応えを受け取る時の二種類の同期ポイント候補...
#br
let calc (in_ch, out_ch) x =
guard (fun () ->
sync (send in_ch x);
receive out_ch)
#br
さぁ、ここから問題が発生します。
receive out_chが同期ポイントなので、応えを受け取るかどう...
すると、「ガードが発動して要求を送っているのに、receiveが...
結果、サーバースレッドの sync (send ...が待ちに入り、サー...
#br
poll (send ...でいいじゃないかと思われるかもしれませんが...
マルチスレッドプログラミングでは、この手の「微妙」なタイ...
#br
この問題への最後の手段としてwrap_abortがあります。
#br
let start_server () =
let in_ch, out_ch =
new_channel (), new_channel ()
in
let rec loop () =
let nack, x = sync (receive in_ch) in
loop (select [send out_ch (x * 2); receive nack])
in
ignore (Thread.create loop ());
in_ch, out_ch
let calc (in_ch, out_ch) x =
guard (fun () ->
let nack = new_channel () in
sync (send in_ch (nack, x));
wrap_abort (receive out_ch) (fun () -> ignore (Threa...
#br
やった、これで解決です、お疲れさまでした。
でも待ってください。毎回nackまで考えなきゃいけないんです...
それに仲介役のスレッドを起動しています。リソース的に優し...
#br
そこで、CMLではivarというスレッド間共有変数を抽象化した便...
#br
> from http://cml.cs.uchicago.edu/pages/sync-var.html
#br
> type 'a ivar
> This is the type constructor for I-structured variables...
#br
まさに、ivarは応えを送るのに最適と書いてあります。
実はCMLのivarは内部的にスレッドを使わずに実装されており、...
ivarを使うと、次のように書けます。
#br
let start_server () =
let in_ch, out_ch =
new_channel (), new_channel ()
in
let rec loop () =
let ivar, x = sync (receive in_ch) in
loop (sync (Ivar.put ivar (x * 2)))
in
ignore (Thread.create loop ());
in_ch, out_ch
let calc (in_ch, out_ch) x =
guard (fun () ->
let ivar = Ivar.make () in
sync (send in_ch (ivar, x));
Ivar.read ivar)
#br
ivarすばらしい。nackもwrap_abortも要らないし、簡単じゃあ...
しかし、冒頭にも紹介しましたが、実はOCamlにはないのです、...
#br
#br
でも大丈夫。実装しました→[[concurrent cell:http://forge.o...
OCamlでも安心してマルチスレッドプログラミングをお楽しみ下...
ちなみにconcurrent cellにはキューやブロードキャストやRPC...
終了行:
[[ivarの必要性]]
OCamlではCMLスタイルのスレッド間通信が可能です。
Eventモジュールには基本的なイベント型やその同期関数が揃っ...
ところが、ivarやmvarといった共有変数が無い為に苦しい状況...
#br
例えばとても単純に、整数を渡して計算結果を(今回は倍にし...
すぐに思いつくのは、次のようなコードです。
#br
let start_server () =
let in_ch, out_ch =
new_channel (), new_channel ()
in
let rec loop () =
let x = sync (receive in_ch) in
loop (sync (send out_ch (x * 2)))
in
ignore (Thread.create loop ());
in_ch, out_ch
let calc (in_ch, out_ch) x =
wrap (send in_ch x) (fun () -> sync (receive out_ch))
#br
これで全く問題ないです。
ただし、同期ポイントが要求を送るときになっている事に注目...
要求を送る時と応えを受け取る時の二種類の同期ポイント候補...
#br
let calc (in_ch, out_ch) x =
guard (fun () ->
sync (send in_ch x);
receive out_ch)
#br
さぁ、ここから問題が発生します。
receive out_chが同期ポイントなので、応えを受け取るかどう...
すると、「ガードが発動して要求を送っているのに、receiveが...
結果、サーバースレッドの sync (send ...が待ちに入り、サー...
#br
poll (send ...でいいじゃないかと思われるかもしれませんが...
マルチスレッドプログラミングでは、この手の「微妙」なタイ...
#br
この問題への最後の手段としてwrap_abortがあります。
#br
let start_server () =
let in_ch, out_ch =
new_channel (), new_channel ()
in
let rec loop () =
let nack, x = sync (receive in_ch) in
loop (select [send out_ch (x * 2); receive nack])
in
ignore (Thread.create loop ());
in_ch, out_ch
let calc (in_ch, out_ch) x =
guard (fun () ->
let nack = new_channel () in
sync (send in_ch (nack, x));
wrap_abort (receive out_ch) (fun () -> ignore (Threa...
#br
やった、これで解決です、お疲れさまでした。
でも待ってください。毎回nackまで考えなきゃいけないんです...
それに仲介役のスレッドを起動しています。リソース的に優し...
#br
そこで、CMLではivarというスレッド間共有変数を抽象化した便...
#br
> from http://cml.cs.uchicago.edu/pages/sync-var.html
#br
> type 'a ivar
> This is the type constructor for I-structured variables...
#br
まさに、ivarは応えを送るのに最適と書いてあります。
実はCMLのivarは内部的にスレッドを使わずに実装されており、...
ivarを使うと、次のように書けます。
#br
let start_server () =
let in_ch, out_ch =
new_channel (), new_channel ()
in
let rec loop () =
let ivar, x = sync (receive in_ch) in
loop (sync (Ivar.put ivar (x * 2)))
in
ignore (Thread.create loop ());
in_ch, out_ch
let calc (in_ch, out_ch) x =
guard (fun () ->
let ivar = Ivar.make () in
sync (send in_ch (ivar, x));
Ivar.read ivar)
#br
ivarすばらしい。nackもwrap_abortも要らないし、簡単じゃあ...
しかし、冒頭にも紹介しましたが、実はOCamlにはないのです、...
#br
#br
でも大丈夫。実装しました→[[concurrent cell:http://forge.o...
OCamlでも安心してマルチスレッドプログラミングをお楽しみ下...
ちなみにconcurrent cellにはキューやブロードキャストやRPC...
ページ名: