Last active
August 30, 2017 13:52
-
-
Save synepis/45299bbad5b5b728dbf72cbc55027660 to your computer and use it in GitHub Desktop.
Ticker
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule Ticker do | |
@interval 2000 | |
def start() do | |
generator_pid = spawn(__MODULE__, :generator, [Queue.new(), Queue.new()]) | |
_ticker_pid = spawn(__MODULE__, :ticker, [generator_pid]) | |
:global.register_name(:generator, generator_pid) | |
end | |
def ticker(generator_pid) do | |
receive do | |
after | |
@interval -> | |
send(generator_pid, { :tick }) | |
ticker(generator_pid) | |
end | |
end | |
@doc""" | |
Sends ticks to all clients sequentially, each tick to next client | |
- Registers new client and adds it to the queue | |
- Sends a tick the next client | |
""" | |
def generator(not_sent, sent) do | |
receive do | |
{ :register, client_pid } -> | |
not_sent = Queue.push(not_sent, client_pid) | |
IO.puts "[generator] client #{inspect(client_pid)} registered" | |
generator(not_sent, sent) | |
{ :tick } -> | |
IO.puts("[generator] tick!") | |
# If all clients have been sent a tick, start the queue again from start | |
{not_sent, sent} = case Queue.empty?(not_sent) do | |
true -> { sent, Queue.new() } | |
false -> { not_sent, sent } | |
end | |
{ not_sent, client } = Queue.pop(not_sent) | |
sent = case client do | |
nil -> # If no clients are available, do nothing | |
sent | |
_ -> # Send a tick to the client and add it to the sent queue | |
send(client, { :tick }) | |
Queue.push(sent, client) | |
end | |
generator(not_sent, sent) | |
end | |
end | |
end | |
defmodule Client do | |
def start() do | |
generator_pid = :global.whereis_name(:generator) | |
pid = spawn(__MODULE__, :listen, []) | |
send(generator_pid, { :register, pid }) | |
end | |
def listen() do | |
receive do | |
{ :tick } -> | |
IO.puts("[#{inspect(self())}] got tick") | |
listen() | |
end | |
end | |
end | |
defmodule Queue do | |
def new(), do: { [], [] } | |
def push({ left, right }, element) do | |
{ [element|left], right } | |
end | |
def empty?({ [], [] }), do: true | |
def empty?({ _, _ }), do: false | |
def pop({ [], [] }), do: { { [], [] }, nil } | |
def pop({ left, [] }), do: pop({ [], Enum.reverse(left) }) | |
def pop({ left, [elem|right] }), do: { { left, right }, elem } | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment