How to perform actions periodically in Erlang

1.2k views Asked by At
-define(INTERVAL, 1000).

init([]) ->
    Timer = erlang:send_after(?INTERVAL, self(), tick),
    {ok, Timer}.

handle_info(tick, OldTimer) ->
    erlang:cancel_timer(OldTimer),
    io:format("Tick ~w~n", [OldTimer]),
    Timer = erlang:send_after(?INTERVAL, self(), tick).
    {noreplay, Timer}.

start_clock() ->
    {_, Timer} = init([]),
    spawn(clock, handle_info, [tick, Timer]).

My codes is as above, but the output is not what I want. How can I integrate init() and handle_info() into the main function(start_clock)?

2

There are 2 answers

1
P_A On BEST ANSWER

I think you need something like this:

start_timer() ->
    gen_server:start_link({local, clock}, ?MODULE, [], []).
0
Pascal On

In the timer module, the function apply_interval(Time, Module, Function, Arguments) executes Module:Function(Arguments) every interval of Time. It takes care of spawning a process, returns a reference to allow a cancellation later.

You also can have a look at send_interval(Time, Pid, Message) in the same library.

You can also implement a simple loop like:

loop(Args,Tick) when is_integer(Tick), Tick >= 0 ->
    receive
        stop -> stopped
    after 
        Tick ->
            do_something(Args),
            {NewArgs,NewTick} = new_args(Args,Tick), 
            loop(NewArgs,NewTick)
    end.

it is not a realtime timer, but the function new_args(Args,Tick) can help to correct the deviation due to process scheduling.