ヽ(´・肉・`)ノログ

How do we fighting without fighting?

すごいE本をElixirでやる(29)

第 12 章 エラーとプロセス - 12.1 リンク - 古い例外、新しいコンセプト から

12.1 リンク

古い例外、新しいコンセプト

捕捉されない結果,捕捉される結果の取得方法がよくわからなかった.

リンクされたプロセスの終了時の挙動 #Erlang - Qiita がよくまとまっていると教えてもらった. 確かにわかりやすい.

優しく(そんなには優しくなく)殺して

通常、kill はどんな方法もうまくいかないときの最終手段です。 終了理由 kill は決して捕捉されないため、他のプロセスがこのメッセージを受け取ったときには、killed に変更されなければいけません。 変更されなければ、リン クされた他のすべてのプロセスが同じ理由 kill で順番に死に、さらに続けて近隣の プロセスが殺されていきます。

なるほど.kill 他の方法がなくなったときに使う.

12.2 モニター

プロセスを殺す必要がない場合につかう.

リンクとは

  1. 一方向である
  2. 2つのプロセス間で複数のモニターが持てる(スタックできて,それぞれに識別子がある)

点が異なる.

モニター(とそのスタック)を使えば、他の関係ないモニターの利用を切り離してライブラリをプログラムできます。 各モニターには一意な識別子があるので、参照したり操作したりするモニターを選択できる。

(互いに存在を知らないような)複数のライブラリが,特定のプロセスで何が起きているかを知るのに役立つ.

Elixir では Process.monitor/1 が利用できる.

iex(1)> Process.monitor(spawn(fn -> Process.sleep(500) end))
Process.monitor(spawn(fn -> Process.sleep(500) end))
#Reference<0.0.3.101>
iex(2)> flush
flush
{:DOWN, #Reference<0.0.3.101>, :process, #PID<0.85.0>, :normal}
:ok
iex(3)>

アトミックにプロセス生成と監視を行うのには Kernel.spawn_monitor/1Kernel.spawn_monitor/3 が使える.

プロセスの監視を止めるには Process.demonitor/2 が使える.

iex(3)> {pid, ref} = spawn_monitor(fn ->
  receive do
    _ -> exit(:boom)
  end
end)
{#PID<0.97.0>, #Reference<0.0.3.128>}
iex(4)> Process.demonitor(ref, [:flush, :info])
Process.demonitor(ref, [:flush, :info])
true
iex(5)> send(pid, :die)
send(pid, :die)
:die
iex(6)> flush
flush
:ok
iex(7)>

info オプションは、モニターを削除しようとしたときにモニターが存在したかどうかを教えてくれ

iex(9)false が返ってきたのはこれが理由

オプションに flush を使うことで、メールボックスに DOWN メッセージがあった場合にはそれを削除でき

iex(10)flush を動かしても,何も返ってきていないのはこれが理由

iex(7)> {pid, ref} = spawn_monitor(fn ->
  receive do
    _ -> exit(:boom)
  end
end)
{pid, ref} = spawn_monitor(fn ->
...(7)>   receive do
...(7)>     _ -> exit(:boom)
...(7)>   end
...(7)> end)
{#PID<0.109.0>, #Reference<0.0.3.158>}
iex(8)> send(pid, :die)
send(pid, :die)
:die
iex(9)> Process.demonitor(ref, [:flush, :info])
Process.demonitor(ref, [:flush, :info])
false
iex(10)> flush
flush
:ok
iex(11)>
このエントリーをはてなブックマークに追加