[Elixir]雑にプロセスの並行処理を書いてみる

Elixirというか、BEAM VMのプロセスが並行に動いてることをさくっと確認するため、個々のプロセスに適当な時間sleepした後にメッセージを返すだけの簡単なプログラムを組んでみました。

テストコード付き。

以下をコピペして、 elixir copy_file.exs で実行するとテストが通ります。

# 実際のコード
defmodule Message do
  def random(upto) when is_integer(upto) and upto > 1 do
    1..upto
    |> Enum.map(fn num ->
      {_, {h, m, s}} = :erlang.localtime
      time = :random.uniform(10_000) / s |> round
      current = self

      spawn_link(fn ->
        time |> :timer.sleep
        send current, {:ok, self, num, time}
      end)
    end)
    loop upto
  end
  def random(upto) when is_integer(upto) and upto <= 1 do
    {:error, [message: "You should set integer more than 1"]}
  end
  def random(_), do: {:error, [message: "You should set integer"]}

  defp loop(num) when num == 0, do: {:ok, [message: "finished !!"]}
  defp loop(num) do
    receive do
      msg ->
        IO.inspect msg
        loop(num - 1)
    end
  end
end

# テストコード
ExUnit.start()
defmodule MessageTest do
  use ExUnit.Case, async: true

  test "should display You should set integer." do
    assert Message.random(:neko) == {:error, [message: "You should set integer"]}
  end

  test "should display You should set integer more than 1." do
    assert Message.random(1) == {:error, [message: "You should set integer more than 1"]}
    assert Message.random(0) == {:error, [message: "You should set integer more than 1"]}
    assert Message.random(-1) == {:error, [message: "You should set integer more than 1"]}
  end

  test "should finish randome message." do
    assert Message.random(2) == {:ok, [message: "finished !!"]}
  end
end

これを個別に実行すると以下のような感じ。
以下は、{:ok, プロセスID, 各プロセスにメッセージを送った順, sleepした時間} です。
これを見ると、個々のプロセスがそれぞれ並行して動作していて、一定時間待ったらgroup_leaderへメッセージを返している、という処理がプロセス毎に並行して実施されていることが確認できます。

iex> Message.random 10
{:ok, #PID<0.81.0>, 5, 130}
{:ok, #PID<0.77.0>, 1, 185}
{:ok, #PID<0.85.0>, 9, 199}
{:ok, #PID<0.80.0>, 4, 209}
{:ok, #PID<0.82.0>, 6, 249}
{:ok, #PID<0.86.0>, 10, 249}
{:ok, #PID<0.84.0>, 8, 278}
{:ok, #PID<0.78.0>, 2, 301}
{:ok, #PID<0.83.0>, 7, 382}
{:ok, #PID<0.79.0>, 3, 394}
{:ok, [message: "finished !!"]}

雑に並行処理を書いてみましたが、これ、少し遊ぶと個々のプロセスを参加者とみなした問題の早解きとかできそうですね。はたまた、個々のプロセスが独立してるとすれば、社会システムを模倣したちょっとしたシミュレーションとかできそう。(やる意味は置いておいて…)

雑に処理を並行させてみた、でした。

広告

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中