何を以ってスレッドプールと呼ぶかは微妙ですがHaskellでスレッドプールもどきを
を表現してみました.
11〜17行目でそれらしい型名を導入しています.
Worker というのがひとつのワーカスレッドです.これは IO () という型で,
Haskell 的には,アクションとよばれる値を表わす型です.アクションは実行
されると入出力を行うような値です.
26行目でワーカスレッドプールを作成しています.ここでは,n 個のワーカの
リストをforkIOをつかって「実行」されると別スレッドで動くアクションのリ
ストに変換しています.これがこのリストがスレッドプールを表現していると
考えることができます.
ワーカは mkWorkerを使って作ります.ワーカはワーカ番号とワーカの開始と
終了を知るためのセマフォとタスクを受けとる口とで作ります.ワーカ本体は,
59〜67行目までで定義されているとおり,
・口からタスクを読むアクション(60行目)
・タスクの有無で選択(61行目)
・タスクない場合は一旦ほかのスレッドに実行を渡すアクション+自分自身(62行目)
・タスクがあった場合は(63行目)
・タスクの種類で選択(64行目)
・終了マークなら,なにもしないアクション(65行目)
・仕事なら,セマフォを掴むアクション
+その仕事
+セマフォを戻すアクション
+自分自身
となっています.
タスクをワーカに渡すのにはMVarを経由します.
細部の説明はきりがないのでここでやめますが,注意点をひとつ.
「実行」と「評価」は別ものです.「実行」は Haskell のプログラムの意味
ににあらわれません.do構文のなかにならんでいる行は,命令型の言語でいう
ところの文(statement)とか命令(command)ではなく,式です.それぞれの式は
「評価」するとアクションとよばれる値を表わしています.
Haskell では do 構文(糖衣)を使ってアクションの並びをひとつのアクション
にまとめます.
ここでは,できるだけ命令型の構文や概念に近くなるように書きました.
正直に白状するとHaskell脳症の頭で考えるのは難しかったです.
より具体的な課題に対してはもっと関数的な Haskell らしい書き方というのが
あるような気がしていますが...
*Main> :main 3
Worker 1 starts at 2007-12-28 10:15:29.973076 UTC
Work 1 starts at 2007-12-28 10:15:29.973809 UTC
Worker 2 starts at 2007-12-28 10:15:29.97446 UTC
Work 2 starts at 2007-12-28 10:15:29.975092 UTC
Worker 3 starts at 2007-12-28 10:15:29.975778 UTC
Work 3 starts at 2007-12-28 10:15:29.976253 UTC
Work 3 ends at 2007-12-28 10:15:38.984953 UTC
Work 2 ends at 2007-12-28 10:15:41.985189 UTC
Work 1 ends at 2007-12-28 10:15:43.984072 UTC
Work 4 starts at 2007-12-28 10:15:43.984574 UTC
Work 6 starts at 2007-12-28 10:15:43.984975 UTC
Work 5 starts at 2007-12-28 10:15:43.985371 UTC
Work 4 ends at 2007-12-28 10:15:50.993701 UTC
Work 6 ends at 2007-12-28 10:15:53.994784 UTC
Work 5 ends at 2007-12-28 10:15:54.995536 UTC
Worker 2 ends at 2007-12-28 10:15:54.996034 UTC
Worker 3 ends at 2007-12-28 10:15:54.996436 UTC
Worker 1 ends at 2007-12-28 10:15:54.996838 UTC
Main thread finished.
nobsun
#5036()
[
Haskell
]
Rating1/1=1.00
何を以ってスレッドプールと呼ぶかは微妙ですがHaskellでスレッドプールもどきを を表現してみました. 11〜17行目でそれらしい型名を導入しています. Worker というのがひとつのワーカスレッドです.これは IO () という型で, Haskell 的には,アクションとよばれる値を表わす型です.アクションは実行 されると入出力を行うような値です. 26行目でワーカスレッドプールを作成しています.ここでは,n 個のワーカの リストをforkIOをつかって「実行」されると別スレッドで動くアクションのリ ストに変換しています.これがこのリストがスレッドプールを表現していると 考えることができます. ワーカは mkWorkerを使って作ります.ワーカはワーカ番号とワーカの開始と 終了を知るためのセマフォとタスクを受けとる口とで作ります.ワーカ本体は, 59〜67行目までで定義されているとおり, ・口からタスクを読むアクション(60行目) ・タスクの有無で選択(61行目) ・タスクない場合は一旦ほかのスレッドに実行を渡すアクション+自分自身(62行目) ・タスクがあった場合は(63行目) ・タスクの種類で選択(64行目) ・終了マークなら,なにもしないアクション(65行目) ・仕事なら,セマフォを掴むアクション +その仕事 +セマフォを戻すアクション +自分自身 となっています. タスクをワーカに渡すのにはMVarを経由します. 細部の説明はきりがないのでここでやめますが,注意点をひとつ. 「実行」と「評価」は別ものです.「実行」は Haskell のプログラムの意味 ににあらわれません.do構文のなかにならんでいる行は,命令型の言語でいう ところの文(statement)とか命令(command)ではなく,式です.それぞれの式は 「評価」するとアクションとよばれる値を表わしています. Haskell では do 構文(糖衣)を使ってアクションの並びをひとつのアクション にまとめます. ここでは,できるだけ命令型の構文や概念に近くなるように書きました. 正直に白状するとHaskell脳症の頭で考えるのは難しかったです. より具体的な課題に対してはもっと関数的な Haskell らしい書き方というのが あるような気がしていますが... *Main> :main 3 Worker 1 starts at 2007-12-28 10:15:29.973076 UTC Work 1 starts at 2007-12-28 10:15:29.973809 UTC Worker 2 starts at 2007-12-28 10:15:29.97446 UTC Work 2 starts at 2007-12-28 10:15:29.975092 UTC Worker 3 starts at 2007-12-28 10:15:29.975778 UTC Work 3 starts at 2007-12-28 10:15:29.976253 UTC Work 3 ends at 2007-12-28 10:15:38.984953 UTC Work 2 ends at 2007-12-28 10:15:41.985189 UTC Work 1 ends at 2007-12-28 10:15:43.984072 UTC Work 4 starts at 2007-12-28 10:15:43.984574 UTC Work 6 starts at 2007-12-28 10:15:43.984975 UTC Work 5 starts at 2007-12-28 10:15:43.985371 UTC Work 4 ends at 2007-12-28 10:15:50.993701 UTC Work 6 ends at 2007-12-28 10:15:53.994784 UTC Work 5 ends at 2007-12-28 10:15:54.995536 UTC Worker 2 ends at 2007-12-28 10:15:54.996034 UTC Worker 3 ends at 2007-12-28 10:15:54.996436 UTC Worker 1 ends at 2007-12-28 10:15:54.996838 UTC Main thread finished.Rating1/1=1.00-0+