LoginSignup
3
3

More than 5 years have passed since last update.

Elixir Processes

Posted at

Elixir Processes

概要

Elixir の Processes について。

Exlixir のコードは Process の中で動いている。
Process はそれぞれ独立している。

Spawn

Process の生成の基本は、自動で import される spawn/1 関数を利用する方法です。

iex> pid = spawn fn -> IO.puts 1 * 2 end
2
#PID<0.76.0>
iex> self
#PID<0.54.0>
iex> Process.alive? pid
false
iex> Process.alive? self
true
iex> Process.info self
[current_function: {Process, :info, 1}, initial_call: {:erlang, :apply, 2},
 status: :running, message_queue_len: 0, messages: [], links: [],
# 略
  fullsweep_after: 65535, minor_gcs: 10], suspending: []]

send and receive

send/2 関数でメッセージ送信
receive/1 関数でメッセージ受信

defmodule ProcessTest do
  def do_receive do
    receive do
      {:key, msg} -> "match " <> msg
      {:other, msg} -> "not match" <> msg
    after
      # wait 1 sec
      1_000 -> "after 1sec"
    end
  end
end

send self, {:key, "value"}
send self, {:other, "other"}
IO.puts ProcessTest.do_receive
IO.puts ProcessTest.do_receive
IO.puts ProcessTest.do_receive
  • 出力
$ elixir process1.exs
match value
not matchother
after 1sec
  • flush
iex  > send self, {:key, "value"}
{:key, "value"}
iex  > send self, {:other, "value"}
{:other, "value"}
iex  > flush
{:key, "value"}
{:other, "value"}
:ok

Links

Process のリンクには spawn_link/1 を利用する。

spawn で例外が発生した場合

例外が伝搬されない

iex  >  spawn fn -> raise "oops" end
#PID<0.70.0>

04:08:03.298 [error] Error in process <0.70.0> with exit value: {#{'__exception__'=>true,'__struct__'=>'Elixir.RuntimeError',message=><<4 bytes>>},[{erlang,apply,2,[]}]}

spawn_link で例外が発生した場合

例外が伝搬される

iex  >  spawn_link fn -> raise "hoge raise" end

04:07:47.831 [error] Error in process <0.67.0> with exit value: {#{'__exception__'=>true,'__struct__'=>'Elixir.RuntimeError',message=><<10 bytes>>},[{erlang,apply,2,[]}]}


** (EXIT from #PID<0.54.0>) an exception was raised:
    ** (RuntimeError) hoge raise
        :erlang.apply/2

Interactive Elixir (1.0.0) - press Ctrl+C to exit (type h() ENTER for help)

States

iex  > defmodule KV do
...  >   def start do
...  >     {:ok, spawn_link(fn -> loop(%{}) end)}
...  >   end
...  >
...  >   defp loop(map) do
...  >     receive do
...  >       {:get, key, caller} ->
...  >         send caller, Map.get(map, key)
...  >         loop(map)
...  >       {:put, key, value} ->
...  >         loop(Map.put(map, key, value))
...  >     end
...  >   end
...  > end
{:module, KV,
 <<70, 79, 82, 49, 0, 0, 6, 144, 66, 69, 65, 77, 69, 120, 68, 99, 0, 0, 0, 94, 131, 104, 2, 100, 0, 14, 101, 108, 105, 120, 105, 114, 95, 100, 111, 99, 115, 95, 118, 49, 108, 0, 0, 0, 2, 104, 2, ...>>,
 {:loop, 1}}
iex  >
nil
iex  > {:ok, pid} = KV.start
{:ok, #PID<0.76.0>}
iex  > send pid, {:get, :hoge, self()}
{:get, :hoge, #PID<0.54.0>}
iex  > flush
nil
:ok
iex  > send pid, {:put, :hoge, :world}
{:put, :hoge, :world}
iex  > send pid, {:get, :hoge, self()}
{:get, :hoge, #PID<0.54.0>}
iex  > flush
:world
:ok
iex  > send pid, {:put, :hoge, :hoge_world2}
{:put, :hoge, :hoge_world2}
iex  > send pid, {:put, :hige, :higeworld2}
{:put, :hige, :higeworld2}
iex  > send pid, {:get, :hoge, self()}
{:get, :hoge, #PID<0.54.0>}
iex  > send pid, {:get, :hige, self()}
{:get, :hige, #PID<0.54.0>}
iex  > flush
:hoge_world2
:higeworld2
:ok
  • プロセスを登録する方法
{:ok, pid} = KV.start
Process.register(pid, :kv)
send :kv, {:get, :hello, self()}

参照

http://elixir-lang.org/docs/stable/elixir/Process.html
http://elixir-lang.org/getting_started/11.html

3
3
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3