Dining philosophers: Difference between revisions

Content added Content deleted
No edit summary
Line 2,071: Line 2,071:


end -- class FORK</lang>
end -- class FORK</lang>

=={{header|Elixir}}==
Implements the Chandy-Misra algorithm.

<lang Elixir>
defmodule DiningPhilosophers do

defstruct missing: [], clean: [], promised: []

def run_demo do
pid1 = spawn(__MODULE__, :init, ["Russell"])
pid2 = spawn(__MODULE__, :init, ["Marx"])
pid3 = spawn(__MODULE__, :init, ["Spinoza"])
pid4 = spawn(__MODULE__, :init, ["Kant"])
pid5 = spawn(__MODULE__, :init, ["Aristotle"])

send(pid1, {:run, %Philosopher{}})
send(pid2, {:run, %Philosopher{missing: [pid1]}})
send(pid3, {:run, %Philosopher{missing: [pid2]}})
send(pid4, {:run, %Philosopher{missing: [pid3]}})
send(pid5, {:run, %Philosopher{missing: [pid1, pid4]}})
end

def init(name) do
receive do
{:run, state} ->
spawn(__MODULE__, :change_state, [self()])
case Enum.random(0..1) do
0 -> thinking(name, state)
1 -> hungry(name, state)
end
end
end

defp thinking(name, state) do
receive do
{:change_state} ->
hungry(name, state)
{:chopstick_request, pid} ->
%{missing: missing} = state
if clean?(pid, state) do
thinking(name, promise_chopstick(name, pid, state))
else
give_chopstick(name, self(), pid)
thinking(name, %{state | missing: [pid | missing]})
end
end
end

defp hungry(name, state) do
IO.puts "#{name} is hungry."
%{missing: missing} = state
for pid <- missing, do: request_chopstick(name, self(), pid)
wait_for_chopsticks(name, state)
end

defp wait_for_chopsticks(name, state) do
%{missing: missing} = state
if Enum.empty?(missing) do
eating(name, state)
end
receive do
{:chopstick_request, pid} ->
%{missing: missing} = state
if clean?(pid, state) do
wait_for_chopsticks(name, promise_chopstick(name, pid, state))
else
give_chopstick(name, self(), pid)
request_chopstick(name, self(), pid)
wait_for_chopsticks(name, %{state | missing: [pid | missing]})
end
{:chopstick_response, pid} ->
%{missing: missing, clean: clean} = state
wait_for_chopsticks(name, %{state | missing: List.delete(missing, pid), clean: [pid | clean]})
end
end

defp eating(name, state) do
IO.puts "*** #{name} is eating."
receive do
{:change_state} ->
%{promised: promised} = state
for pid <- promised, do: give_chopstick(name, self(), pid)
thinking(name, %Philosopher{missing: promised})
end
end

defp clean?(pid, state) do
%{clean: clean} = state
Enum.member?(clean, pid)
end

defp promise_chopstick(name, pid, state) do
IO.puts "#{name} promises a chopstick."
%{promised: promised} = state
%{state | promised: [pid | promised]}
end

defp request_chopstick(name, snd_pid, recv_pid) do
IO.puts "#{name} requests a chopstick."
send(recv_pid, {:chopstick_request, snd_pid})
end

defp give_chopstick(name, snd_pid, recv_pid) do
IO.puts "#{name} gives a chopstick."
send(recv_pid, {:chopstick_response, snd_pid})
end

def change_state(pid) do
Process.sleep(Enum.random(1..10) * 1000)
send(pid, {:change_state})
change_state(pid)
end
end
</lang>



=={{header|Erlang}}==
=={{header|Erlang}}==