Data commit
This commit is contained in:
parent
7387c8f97b
commit
cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions
121
Task/Dining-philosophers/Elixir/dining-philosophers.elixir
Normal file
121
Task/Dining-philosophers/Elixir/dining-philosophers.elixir
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
defmodule Philosopher 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"])
|
||||
|
||||
# a chopstick is simply represented by the pid of the neighbour that shares it.
|
||||
|
||||
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(philosopher_name) do
|
||||
receive do
|
||||
{:run, state} ->
|
||||
spawn(__MODULE__, :change_state, [self()])
|
||||
case flip_coin() do
|
||||
:heads -> thinking(philosopher_name, state)
|
||||
:tails -> hungry(philosopher_name, state)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
defp thinking(philosopher_name, state) do
|
||||
receive do
|
||||
{:change_state} ->
|
||||
hungry(philosopher_name, state)
|
||||
{:chopstick_request, pid} ->
|
||||
if clean?(pid, state) do
|
||||
thinking(philosopher_name, promise_chopstick(philosopher_name, pid, state))
|
||||
else
|
||||
give_chopstick(philosopher_name, self(), pid)
|
||||
%{missing: missing} = state
|
||||
thinking(philosopher_name, %{state | missing: [pid | missing]})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
defp hungry(philosopher_name, state) do
|
||||
IO.puts "#{philosopher_name} is hungry."
|
||||
%{missing: missing} = state
|
||||
for pid <- missing, do: request_chopstick(philosopher_name, self(), pid)
|
||||
wait_for_chopsticks(philosopher_name, state)
|
||||
end
|
||||
|
||||
defp wait_for_chopsticks(philosopher_name, state) do
|
||||
if has_chopsticks?(state) do
|
||||
eating(philosopher_name, state)
|
||||
end
|
||||
receive do
|
||||
{:chopstick_request, pid} ->
|
||||
if clean?(pid, state) do
|
||||
wait_for_chopsticks(philosopher_name, promise_chopstick(philosopher_name, pid, state))
|
||||
else
|
||||
give_chopstick(philosopher_name, self(), pid)
|
||||
request_chopstick(philosopher_name, self(), pid)
|
||||
%{missing: missing} = state
|
||||
wait_for_chopsticks(philosopher_name, %{state | missing: [pid | missing]})
|
||||
end
|
||||
{:chopstick_response, pid} ->
|
||||
%{missing: missing, clean: clean} = state
|
||||
wait_for_chopsticks(philosopher_name, %{state | missing: List.delete(missing, pid), clean: [pid | clean]})
|
||||
end
|
||||
end
|
||||
|
||||
defp eating(philosopher_name, state) do
|
||||
IO.puts "*** #{philosopher_name} is eating."
|
||||
receive do
|
||||
{:change_state} ->
|
||||
%{promised: promised} = state
|
||||
for pid <- promised, do: give_chopstick(philosopher_name, self(), pid)
|
||||
thinking(philosopher_name, %Philosopher{missing: promised})
|
||||
end
|
||||
end
|
||||
|
||||
defp clean?(pid, state) do
|
||||
%{clean: clean} = state
|
||||
Enum.member?(clean, pid)
|
||||
end
|
||||
|
||||
defp has_chopsticks?(state) do
|
||||
%{missing: missing} = state
|
||||
Enum.empty?(missing)
|
||||
end
|
||||
|
||||
defp promise_chopstick(philosopher_name, pid, state) do
|
||||
IO.puts "#{philosopher_name} promises a chopstick."
|
||||
%{promised: promised} = state
|
||||
%{state | promised: [pid | promised]}
|
||||
end
|
||||
|
||||
defp request_chopstick(philosopher_name, snd_pid, recv_pid) do
|
||||
IO.puts "#{philosopher_name} requests a chopstick."
|
||||
send(recv_pid, {:chopstick_request, snd_pid})
|
||||
end
|
||||
|
||||
defp give_chopstick(philosopher_name, snd_pid, recv_pid) do
|
||||
IO.puts "#{philosopher_name} gives a chopstick."
|
||||
send(recv_pid, {:chopstick_response, snd_pid})
|
||||
end
|
||||
|
||||
defp flip_coin do
|
||||
case Enum.random(0..1) do
|
||||
0 -> :heads
|
||||
1 -> :tails
|
||||
end
|
||||
end
|
||||
|
||||
def change_state(pid) do
|
||||
Process.sleep(Enum.random(1..10) * 1000)
|
||||
send(pid, {:change_state})
|
||||
change_state(pid)
|
||||
end
|
||||
Loading…
Add table
Add a link
Reference in a new issue