Skip to content

Instantly share code, notes, and snippets.

@ryo33
Last active December 2, 2018 01:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ryo33/0e3dfb374fdd9a76846ea361d7bab836 to your computer and use it in GitHub Desktop.
Save ryo33/0e3dfb374fdd9a76846ea361d7bab836 to your computer and use it in GitHub Desktop.
食事する哲学者の問題 with Cizen ref: https://qiita.com/ryo33/items/3d3fc82cdcb929e0b9ec
mix new cizen_dining_philosophers
cd cizen_dining_philosophers
defp deps do
[
{:cizen, "~> 0.14.1"}
]
end
defmodule BorrowChopstick do
defstruct [:chopstick_id]
use Cizen.Request # to use defresponse/3
defresponse LendChopstick, :request_id do
defstruct [:request_id]
end
end
defmodule ReturnChopstick do
defstruct [:chopstick_id]
end
defmodule Chopstick do
use Cizen.Automaton
defstruct []
alias Cizen.Effects.{Dispatch, Receive, Subscribe}
alias Cizen.{Event, Filter}
@impl true
def spawn(id, %__MODULE__{}) do
perform id, %Subscribe{
event_filter: Filter.any([
Filter.new(fn %Event{body: %BorrowChopstick{chopstick_id: ^id}} -> true end),
Filter.new(fn %Event{body: %ReturnChopstick{chopstick_id: ^id}} -> true end)
])
}
:available
end
@impl true
def yield(id, :available) do
received = perform id, %Receive{
event_filter: Filter.new(fn %Event{body: %BorrowChopstick{}} -> true end)
}
alias BorrowChopstick.LendChopstick
perform id, %Dispatch{
body: %LendChopstick{
request_id: received.id
}
}
:not_available
end
@impl true
def yield(id, :not_available) do
perform id, %Receive{
event_filter: Filter.new(fn %Event{body: %ReturnChopstick{}} -> true end)
}
:available
end
end
defmodule Philosopher do
use Cizen.Automaton
defstruct [:name, :left_chopstick, :right_chopstick]
alias Cizen.Effects.{Request, Dispatch}
@impl true
def spawn(_id, struct) do
{:hungry, struct}
end
@impl true
def yield(id, {:hungry, struct}) do
%__MODULE__{
name: name,
left_chopstick: left_chopstick,
right_chopstick: right_chopstick
} = struct
IO.puts("#{name} is hungry.")
perform id, %Request{
body: %BorrowChopstick{
chopstick_id: left_chopstick
}
}
IO.puts("#{name} has a chopstick in their left hand.")
perform id, %Request{
body: %BorrowChopstick{
chopstick_id: right_chopstick
}
}
IO.puts("#{name} has chopstics in both hands.")
{:eating, struct}
end
@impl true
def yield(id, {:eating, struct}) do
%__MODULE__{
name: name,
left_chopstick: left_chopstick,
right_chopstick: right_chopstick
} = struct
IO.puts("#{name} is eating.")
perform id, %Dispatch{
body: %ReturnChopstick{
chopstick_id: left_chopstick
}
}
perform id, %Dispatch{
body: %ReturnChopstick{
chopstick_id: right_chopstick
}
}
{:hungry, struct}
end
end
defmodule Dining do
use Cizen.Effectful # for handle/1 and perform/2
alias Cizen.Effects.{All, Start}
def run do
handle fn id ->
chopstick_1 = perform id, %Start{saga: %Chopstick{}}
chopstick_2 = perform id, %Start{saga: %Chopstick{}}
chopstick_3 = perform id, %Start{saga: %Chopstick{}}
chopstick_4 = perform id, %Start{saga: %Chopstick{}}
chopstick_5 = perform id, %Start{saga: %Chopstick{}}
philosophers = [
%Philosopher{
name: "Plato",
left_chopstick: chopstick_1,
right_chopstick: chopstick_2
},
%Philosopher{
name: "Konfuzius",
left_chopstick: chopstick_2,
right_chopstick: chopstick_3
},
%Philosopher{
name: "Socrates",
left_chopstick: chopstick_3,
right_chopstick: chopstick_4
},
%Philosopher{
name: "Voltaire",
left_chopstick: chopstick_4,
right_chopstick: chopstick_5
},
%Philosopher{
name: "Descartes",
left_chopstick: chopstick_5,
right_chopstick: chopstick_1
}
]
perform id, %All{
effects: Enum.map(philosophers, &(%Start{saga: &1}))
}
receive do
_ -> :ok
end
end
end
end
Dining.run
Plato is hungry.
Konfuzius is hungry.
Socrates is hungry.
Voltaire is hungry.
Descartes is hungry.
Plato has a chopstick in their left hand.
Konfuzius has a chopstick in their left hand.
Socrates has a chopstick in their left hand.
Voltaire has a chopstick in their left hand.
Descartes has a chopstick in their left hand.
%Philosopher{
name: "Descartes",
left_chopstick: chopstick_1,
right_chopstick: chopstick_5
}
Plato is hungry.
Konfuzius is hungry.
Socrates is hungry.
Voltaire is hungry.
Descartes is hungry.
Plato has a chopstick in their left hand.
Konfuzius has a chopstick in their left hand.
Socrates has a chopstick in their left hand.
Voltaire has a chopstick in their left hand.
Voltaire has chopstics in both hands.
Voltaire is eating.
Voltaire is hungry.
Socrates has chopstics in both hands.
Socrates is eating.
Socrates is hungry.
Konfuzius has chopstics in both hands.
Konfuzius is eating.
Voltaire has a chopstick in their left hand.
Konfuzius is hungry.
Plato has chopstics in both hands.
Plato is eating.
Plato is hungry.
Socrates has a chopstick in their left hand.
Voltaire has chopstics in both hands.
Voltaire is eating.
Voltaire is hungry.
Descartes has a chopstick in their left hand.
Konfuzius has a chopstick in their left hand.
Socrates has chopstics in both hands.
Socrates is eating.
Socrates is hungry.
Descartes has chopstics in both hands.
Descartes is eating.
Descartes is hungry.
.
.
.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment