I was going to ask:
I don’t understand why you have to
run()
when getting the state.
But you’re using the @timedelay
as a ticking clock.
Just use a timer instead.
def init([]) do
:random.seed(:os.timestamp)
time = :random.uniform
voltage = :math.sin(2 * :math.pi + time)
timer_ref = Process.send_after(self(), :tick, @timedelay)
state = %{time: time, voltage: voltage, timer: timer_ref}
{:ok, state}
end
def handle_cast(:run, state) do
# clear timer or if sent let :tick be handled by handle_info
if Process.clear_timer(state.timer) do
new_state = run(state)
timer_ref = Process.send_after(self(), :tick, @timedelay)
{:noreply, %{new_state | timer: timer_ref}}
else
{:noreply, state}
end
end
def handle_info(:tick, state) do
new_state = run(state) # <------------ ALWAYS HAS TO RUN IT
timer_ref = Process.send_after(self(), :tick, @timedelay)
{:noreply, %{new_state | timer: timer_ref}}
end
def handle_call({:get_state, pid}, _from, state) do
IO.puts "getting state"
return = Map.take(state, [:time, :voltage])
{:reply, return, state}
end
defp run(state) do
new_time = state.time + :random.uniform/12
new_voltage = :math.sin(2 * :math.pi + new_time)
new_state = %{state | time: new_time, voltage: new_voltage}
IO.puts "VALUES #{inspect self()} t/v #{new_time}/#{new_voltage}"
new_state
end
end
At least, if I correctly understand what you are trying to do. If not, tell me what I missed.