簡単Elixirシリーズ
~ プロセスを知ろう② ~
この記事は「Elixir Advent Calendar 2022」21日目の記事です
東京にいるけどfukuokaexのYOSUKEです。
簡単 Elixirシリーズでは小ネタをサクッと書いていこう。というコンセプトで作っていきます。
今回は、プロセスについて公式ドキュメントを見ながらサクッと解説の第2段です。
さて、前回の記事の続きものです、ちなみに前回の記事はこちらです。
今回は、Elixirのプロセスをさらに知る為に、例と共にさらに理解を深めていきたいと思います。
まずは、call
に文字列を出力する無銘関数を作成。 そこに self()
関数で自分のプロセスIDを出力するようにします。
spawn(call)
でcallを呼び出しプロセスを生み出します。生み出されたプロセスは、呼ばれた関数を実行します。
実行が終わったら、このプロセスは終了します。
ここでは、pid
に生み出されたプロセスIDを束縛しておき、その後 Process.alive?(pid)
でこのプロセスが生きてるか確認しています。
当然、実行後すぐにプロセスが終了しているので、false
が返ってきます。
iex()> call = fn -> IO.puts "process id is #{inspect(self())}." end
#Function<45.65746770/0 in :erl_eval.expr/5>
iex()> pid = spawn(call)
process id is #PID<0.112.0>.
#PID<0.112.0>
Process.alive?(pid)
false
プロセスのライフサイクルが何となく理解できたでしょうか?
次は、メッセージ機能について例えを利用して見ていきます。
defmodule MyProcess do
def await_receive_msg(x, y) do
IO.puts "プロセス #{inspect(self())}, メッセージ待ち中"
receive do
"Go" -> IO.puts "x + y = #{x + y}"
"Quit" -> IO.puts "計算をやめます。"
_ -> IO.puts "なんか別のメッセージが送られてきました"
end
IO.puts "プロセス #{inspect(self())} は実行し終えたので終了します。"
end
end
例えば、こんな関数を書いておきます。
実行時にはspwan()
を利用して、PIDを取得し、 PID毎に send(pid, "Quit"}
などとして
メッセージを送って関数の実行をしているのが見えます。
iex(1)> pid = spawn(MyProcess, :await_receive_msg, [2, 1])
#PID<0.111.0>
プロセス #PID<0.111.0>, メッセージ待ち中
iex(2)> pid2 = spawn(MyProcess, :await_receive_msg, [3, 4])
プロセス #PID<0.113.0>, メッセージ待ち中
#PID<0.113.0>
iex(3)> Process.alive? pid
true
iex(4)> Process.alive? pid2
true
iex(5)> send(pid, "Quit")
計算をやめます。
プロセス #PID<0.111.0> は実行し終えたので終了します。
"Quit"
iex(6)> Process.alive? pid
false
iex(7)> Process.alive? pid2
true
iex(8)> send(pid2, "Go")
"Go"
7
プロセス #PID<0.113.0> は実行し終えたので終了します。
iex(9)> Process.alive? pid2
false
このコードをさらに改良して、実行後にまた自分自身を呼び出すように書き換えて見ます。
defmodule MyProcess do
def await_receive_msg() do
IO.puts "プロセス #{inspect(self())}, メッセージ待ち中"
receive do
{x, y} -> IO.puts "x + y = #{x + y}"
await_receive_msg()
"Quit" -> IO.puts "計算をやめます。"
await_receive_msg()
_ -> IO.puts "なんか別のメッセージが送られてきました"
await_receive_msg()
end
end
end
実行してみます。 計算の引数を msg として受けつけるように変更した事に注意してください。
iex()> pid = spawn(MyProcess, :await_receive_msg, [])
プロセス #PID<0.140.0>, メッセージ待ち中
#PID<0.140.0>
iex(16)> send(pid, "Quit")
計算をやめます。
プロセス #PID<0.140.0>, メッセージ待ち中
"Quit"
iex()> send(pid, {1, 3})
x + y = 4
{1, 3}
プロセス #PID<0.140.0>, メッセージ待ち中
iex()> send(pid, [1,2])
なんか別のメッセージが送られてきました
[1, 2]
プロセス #PID<0.140.0>, メッセージ待ち中
プロセスが終了せずに状態まちをするようになりました。
さて、ここまで来ると、状態を保持する例も見て見たくなりますね。が、長くなるので、それは 第3段にまとめていきたいと思います。