Concurrent Clean : マルチスレッドとグラフの共有
Cleanでマルチスレッドプログラミングを実装するに置いては、気になるのがグラフの共有。
一見、純粋関数型言語なので全部immutableだからいいじゃん、と思うかもしれないが、Erlangのようにeagerに評価しないので、あるグラフが未評価であった場合に、複数のスレッドでグラフを共有すると排他制御を考える必要が出てくる。
それでは、式の評価をすべてsynchronizedしていしてやれば安全になるが、それでは同期化のための無駄なオーバーヘッドが多く発生してしまう。そこで、必要な部分だけ、明示的に同期化するように指定してやる必要がある。
::Synchronized a = Syncronized a synchronize :: *a -> *(Synchronized a) ... # s = synchronize (['a '] ++ ['message '] ++ ['to send']) = send_message s unit
というように、synchronizeという関数を用意して、これを通すことで、グラフにマークをつけて同期化を強制するというアイデアは上手くいきそうだ。ただし、synchronizeという関数は、実は通常の関数ではなく、システムで用意する特殊なプリミティブとして提供する。
ところで、次のように、一意性型属性を付けてやることで、共有を不可にするというアイデアは上手く行かない。
send_message :: *a Unit -> Unit
というのは、「*{a::[Int]}」というようにレコード型にリストを包んだときには、一意になるのは外側のレコードだけであって、内側のリストは共有することができる。内側のリストまで一意にするには「*{a::*[Int]}」とする必要があるが、これは、関数の型としては指定できない。