Skip to content

Instantly share code, notes, and snippets.

@synepis
Last active August 30, 2017 13:52
Show Gist options
  • Save synepis/45299bbad5b5b728dbf72cbc55027660 to your computer and use it in GitHub Desktop.
Save synepis/45299bbad5b5b728dbf72cbc55027660 to your computer and use it in GitHub Desktop.
Ticker
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