Skip to content

Commit c01e409

Browse files
committed
Add timer:send_after/2,3 and apply_after/4
Implement timer:send_after/2, timer:send_after/3 and timer:apply_after/4 using timer_manager. Add tests for all three functions. Signed-off-by: Peter M <petermm@gmail.com>
1 parent d4ad8a3 commit c01e409

3 files changed

Lines changed: 96 additions & 1 deletion

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1313
- Added generic unix support for uart using POSIX nifs
1414
- Added RISC-V 64-bit (RV64IMAC) JIT backend
1515
- Added DWARF debug information support for JIT-compiled code
16+
- Added `timer:send_after/2`, `timer:send_after/3` and `timer:apply_after/4`
1617

1718
### Changed
1819
- ~10% binary size reduction by rewriting module loading logic

libs/estdlib/src/timer.erl

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
%%-----------------------------------------------------------------------------
2828
-module(timer).
2929

30-
-export([sleep/1]).
30+
-export([sleep/1, send_after/2, send_after/3, apply_after/4]).
3131

3232
%%-----------------------------------------------------------------------------
3333
%% @param Timeout number of milliseconds to sleep or `infinity'
@@ -43,3 +43,53 @@ sleep(Timeout) ->
4343
after Timeout ->
4444
ok
4545
end.
46+
47+
%%-----------------------------------------------------------------------------
48+
%% @param Time time in milliseconds after which to send the message.
49+
%% @param Message the message to send to the calling process.
50+
%% @returns `{ok, TRef}' where `TRef' is a reference to the timer.
51+
%%
52+
%% @doc Sends `Message' to the calling process after `Time' milliseconds.
53+
%% @end
54+
%%-----------------------------------------------------------------------------
55+
-spec send_after(Time :: non_neg_integer(), Message :: term()) -> {ok, reference()}.
56+
send_after(Time, Message) ->
57+
TRef = timer_manager:send_after(Time, self(), Message),
58+
{ok, TRef}.
59+
60+
%%-----------------------------------------------------------------------------
61+
%% @param Time time in milliseconds after which to send the message.
62+
%% @param Pid the process to which to send the message.
63+
%% @param Message the message to send.
64+
%% @returns `{ok, TRef}' where `TRef' is a reference to the timer.
65+
%%
66+
%% @doc Sends `Message' to `Pid' after `Time' milliseconds.
67+
%% @end
68+
%%-----------------------------------------------------------------------------
69+
-spec send_after(Time :: non_neg_integer(), Pid :: pid() | atom(), Message :: term()) ->
70+
{ok, reference()}.
71+
send_after(Time, Pid, Message) ->
72+
TRef = timer_manager:send_after(Time, Pid, Message),
73+
{ok, TRef}.
74+
75+
%%-----------------------------------------------------------------------------
76+
%% @param Time time in milliseconds after which to apply the function.
77+
%% @param Module the module of the function to apply.
78+
%% @param Function the function to apply.
79+
%% @param Arguments the arguments to pass to the function.
80+
%% @returns `{ok, TRef}' where `TRef' is a reference to the timer.
81+
%%
82+
%% @doc Applies `Module:Function(Arguments)' after `Time' milliseconds.
83+
%% @end
84+
%%-----------------------------------------------------------------------------
85+
-spec apply_after(
86+
Time :: non_neg_integer(), Module :: module(), Function :: atom(), Arguments :: [term()]
87+
) -> {ok, reference()}.
88+
apply_after(Time, Module, Function, Arguments) ->
89+
Pid = spawn(fun() ->
90+
receive
91+
apply_now -> apply(Module, Function, Arguments)
92+
end
93+
end),
94+
TRef = timer_manager:send_after(Time, Pid, apply_now),
95+
{ok, TRef}.

tests/libs/estdlib/test_timer.erl

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ test() ->
2929
ok = test_timer_loop(),
3030
ok = test_timer_badargs(),
3131
ok = test_infinity(),
32+
ok = test_send_after_2(),
33+
ok = test_send_after_3(),
34+
ok = test_apply_after(),
3235
ok.
3336

3437
test_timer() ->
@@ -80,3 +83,44 @@ test_infinity() ->
8083
ok ->
8184
ok = etest:assert_true(erlang:is_process_alive(Pid))
8285
end.
86+
87+
test_send_after_2() ->
88+
{ok, _TRef} = timer:send_after(500, hello),
89+
receive
90+
hello -> {error, too_early}
91+
after 250 ->
92+
ok
93+
end,
94+
receive
95+
hello -> ok
96+
after 10000 ->
97+
{error, timeout}
98+
end.
99+
100+
test_send_after_3() ->
101+
Self = self(),
102+
{ok, _TRef} = timer:send_after(500, Self, hello_dest),
103+
receive
104+
hello_dest -> {error, too_early}
105+
after 250 ->
106+
ok
107+
end,
108+
receive
109+
hello_dest -> ok
110+
after 10000 ->
111+
{error, timeout}
112+
end.
113+
114+
test_apply_after() ->
115+
Self = self(),
116+
{ok, _TRef} = timer:apply_after(500, erlang, send, [Self, apply_result]),
117+
receive
118+
apply_result -> {error, too_early}
119+
after 250 ->
120+
ok
121+
end,
122+
receive
123+
apply_result -> ok
124+
after 10000 ->
125+
{error, timeout}
126+
end.

0 commit comments

Comments
 (0)