ヽ(´・肉・`)ノログ

How do we fighting without fighting?

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

第 11 章マルチプロセスについてもっと から

11.1 状態を述べろ

defmodule Kitchen do
  def fridge1 do
    receive do
      {from, {:store, _food}} ->
        send from, {self, :ok}
        fridge1
      {from, {:take, _food}} ->
        # uh...
        send from, {self, :not_found}
      :terminate ->
        :ok
    end
  end

  def fridge2(food_list) do
    receive do
      {from, {:store, food}} ->
        send from, {self, :ok}
        fridge2([food | food_list])
      {from, {:take, food}} ->
        if Enum.member?(food_list, food) do
          send from, {self, {:ok, food}}
          # List.delete/2 doesn't match to use here.
          # `List.delete([1, 2, 2, 3], 2)` returns `[1, 3]`
          # But we need `[1, 2, 3]`
          fridge2(:lists.delete(food, food_list))
        else
          send from, {self, :not_found}
          fridge2(food_list)
        end
      :terminate ->
        :ok
    end
  end
end
Eshell V8.0.2  (abort with ^G)
Interactive Elixir (1.3.2) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> c("kitchen.exs")
c("kitchen.exs")
[Kitchen]
iex(2)> pid = spawn(Kitchen, :fridge2, [[:baking_soda]])
pid = spawn(Kitchen, :fridge2, [[:baking_soda]])
#PID<0.89.0>
iex(3)> send pid, {self, {:store, :milk}}
send pid, {self, {:store, :milk}}
{#PID<0.81.0>, {:store, :milk}}
iex(4)> flush
flush
{#PID<0.89.0>, :ok}
:ok
iex(5)> send pid, {self, {:store, :bacon}}
send pid, {self, {:store, :bacon}}
{#PID<0.81.0>, {:store, :bacon}}
iex(6)> send pid, {self, {:take, :bacon}}
send pid, {self, {:take, :bacon}}
{#PID<0.81.0>, {:take, :bacon}}
iex(7)> send pid, {self, {:take, :turkey}}
send pid, {self, {:take, :turkey}}
{#PID<0.81.0>, {:take, :turkey}}
iex(8)> flush
flush
{#PID<0.89.0>, :ok}
{#PID<0.89.0>, {:ok, :bacon}}
{#PID<0.89.0>, :not_found}
:ok
iex(9)>

さらに面白いことに、メールボックスがそのようにできているので、 たとえ同時に 1000 人が急に冷蔵庫の中にある七面鳥の最後の一切れを求めてやってきても、 1 人だけがそれを得られます。

特に排他制御を意識しなくてもうまくやってくれるということだ.便利.

このエントリーをはてなブックマークに追加