Jump to content

Dining philosophers: Difference between revisions

no edit summary
No edit summary
Line 2,071:
 
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}}==
Anonymous user
Cookies help us deliver our services. By using our services, you agree to our use of cookies.