Timer
Mix.install([
{:jason, "~> 1.4"},
{:kino, "~> 0.9", override: true},
{:youtube, github: "brooklinjazz/youtube"},
{:hidden_cell, github: "brooklinjazz/hidden_cell"}
])
Navigation
Home Report An Issue Score TrackerSupervisorsTimer
You’re going to create a Timer GenServer which when spawned, will send itself a message every second to increment an internal count.
You should be able to retrieve the number of seconds that have passed since the Timer was spawned using a Timer.seconds/1 function.
{:ok, pid} = Timer.start_link([])
Timer.seconds(pid)
0
Process.sleep(1000)
Timer.seconds(pid)
2
Keep in mind, we cannot guarantee perfect timing when sending messages on an interval, and that is not the purpose of this exercise.
Example Solution
defmodule Timer do
use GenServer
def start_link(_opts) do
GenServer.start_link(__MODULE__, [])
end
def seconds(timer_pid) do
GenServer.call(timer_pid, :seconds)
end
@impl true
def init(_opts) do
schedule_timer()
{:ok, 0}
end
@impl true
def handle_info(:increment, state) do
schedule_timer()
{:noreply, state + 1}
end
@impl true
def handle_call(:seconds, _from, state) do
{:reply, state, state}
end
defp schedule_timer do
Process.send_after(self(), :increment, 1000)
end
end
Implement the Timer module as documented below. You will also have to implement the necessary GenServer callback functions such as GenServer.init/1, GenServer.handle_info/2, and GenServer.handle_call/3.
defmodule Timer do
@moduledoc """
Documentation for `Timer`
"""
use GenServer
@doc """
Start the `Timer` process.
## Examples
iex> {:ok, pid} = Timer.start_link([])
"""
def start_link(_opts) do
end
@doc """
Get the number of seconds that have elapsed since the `Timer` was started.
## Examples
iex> {:ok, pid} = Timer.start_link([])
iex> Timer.seconds(pid)
0
iex> Process.sleep(1200)
iex> Timer.seconds(pid)
1
"""
def seconds(timer_pid) do
end
end
Bonus :timer
Re-implement your Timer module using the erlang :timer library. If already wrote your solution using the :timer library, then re-implement it using Process.send_after/4.
Example Solution
defmodule AlternateTimer do
use GenServer
def start_link(_opts) do
GenServer.start_link(__MODULE__, [])
end
def seconds(timer_pid) do
GenServer.call(timer_pid, :seconds)
end
@impl true
def init(_opts) do
:timer.send_interval(1000, self(), :increment)
{:ok, 0}
end
@impl true
def handle_call(:seconds, _from, state) do
{:reply, state, state}
end
@impl true
def handle_info(:increment, state) do
{:noreply, state + 1}
end
end
defmodule AlternateTimer do
@moduledoc """
Documentation for `Timer`
"""
use GenServer
@doc """
Start the `Timer` process.
"""
def start_link(_opts) do
GenServer.start_link(__MODULE__, [])
end
@doc """
Get the number of seconds that have elapsed since the `Timer` was started.
"""
def seconds(timer_pid) do
GenServer.call(timer_pid, :seconds)
end
end
Commit Your Progress
DockYard Academy now recommends you use the latest Release rather than forking or cloning our repository.
Run git status to ensure there are no undesirable changes.
Then run the following in your command line from the curriculum folder to commit your progress.
$ git add .
$ git commit -m "finish Timer exercise"
$ git push
We’re proud to offer our open-source curriculum free of charge for anyone to learn from at their own pace.
We also offer a paid course where you can learn from an instructor alongside a cohort of your peers. We will accept applications for the June-August 2023 cohort soon.