Worker
同じ重い合計を二度走らせる画面です。片方はページの中、もう片方は別のスレッドです。横で数字が 60ms ごとに動いているので、どちらのときに画面が止まるかが見えます。
止まるのはメールボックスのせいではない
JavaScript は一本しか走りません。同期で回る計算は、誰が書いても画面を止めます。 アクタの仕組みとは関係ありません。測るとこうなります。
| 300ms の計算をどこで回すか | 他のアクタが感じた最大の間隔 |
|---|---|
| 同じスレッド | 338 ms |
| Worker | 34 ms(何もしていないときと同じ) |
置き場所を書くのは一行だけ
仕事をするアクタは、普通の ActorRef で掴みます。
a := Worker spawn: (Adder named: '集計' to: sink) on: w.
(a ask sumTo: 100000) forced printNl.
どこで走るかを言っているのは Worker spawn:on: の一行だけです。ask も tell も、相手が同じスレッドにいるときと同じに書きます。参照には、そのアクタがどこで動くかが書かれていません。
渡せないものはコンパイル時に止まる
スレッドを跨ぐとき、状態もメッセージもコピーされて渡ります。だからブロックは渡せません。作られた場所を閉じ込めているからです。
これはコンパイル時に止まります。ブロックを持った状態を Worker に置こうとすると、どの項目が原因かまで言われます。
the state placed on a worker cannot cross an actor boundary: it is Job,
whose work is Block[Int -> Int], and a block closes over the scope it was
made in
Decimal も Date も Dict も、意味を保ったまま渡ります。structuredClone にそのまま任せると、Decimal は中身がむき出しの入れ物になって届きます。金額が境界を越えて金額でなくなるので、線上の表現は自前で持っています。
落ちたときも同じ
Worker の上のアクタを落とすと、監視している側に down: が届きます。スレッドを跨いでも同じです。