Created
October 26, 2016 21:05
-
-
Save minhajuddin/064226d73d5648aa73364218e862a497 to your computer and use it in GitHub Desktop.
A ticker for elixir, which emits a tick event for every interval
This file contains 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 | |
require Logger | |
# public api | |
def start(recipient_pid, tick_interval, duration \\ :infinity) do | |
# Process.monitor(pid) # what to do if the process is dead before this? | |
# start a process whose only responsibility is to wait for the interval | |
ticker_pid = spawn(__MODULE__, :loop, [recipient_pid, tick_interval, 0]) | |
# and send a tick to the recipient pid and loop back | |
send(ticker_pid, :send_tick) | |
schedule_terminate(ticker_pid, duration) | |
# returns the pid of the ticker, which can be used to stop the ticker | |
ticker_pid | |
end | |
def stop(ticker_pid) do | |
send(ticker_pid, :terminate) | |
end | |
# internal api | |
def loop(recipient_pid, tick_interval, current_index) do | |
receive do | |
:send_tick -> | |
send(recipient_pid, {:tick, current_index}) # send the tick event | |
Process.send_after(self, :send_tick, tick_interval) # schedule a self event after interval | |
loop(recipient_pid, tick_interval, current_index + 1) | |
:terminate -> | |
:ok # terminating | |
# NOTE: we could also optionally wire it up to send a last_tick event when it terminates | |
send(recipient_pid, {:last_tick, current_index}) | |
oops -> | |
Logger.error("received unexepcted message #{inspect oops}") | |
loop(recipient_pid, tick_interval, current_index + 1) | |
end | |
end | |
defp schedule_terminate(_pid, :infinity), do: :ok | |
defp schedule_terminate(ticker_pid, duration), do: Process.send_after(ticker_pid, :terminate, duration) | |
end | |
defmodule Listener do | |
def start do | |
Ticker.start self, 500, 2000 # will send approximately 4 messages | |
end | |
def run do | |
receive do | |
{:tick, _index} = message -> | |
IO.inspect(message) | |
run | |
{:last_tick, _index} = message -> | |
IO.inspect(message) | |
:ok | |
end | |
end | |
end | |
Listener.start | |
Listener.run | |
# will output | |
# => {:tick, 0} | |
# => {:tick, 1} | |
# => {:tick, 2} | |
# => {:tick, 3} | |
# => {:last_tick, 4} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment