Skip to content

Commit b09545a

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 b09545a

3 files changed

Lines changed: 99 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: 47 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,47 @@ 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+
ok = etest:assert_true(is_reference(TRef)),
90+
receive
91+
hello -> {error, too_early}
92+
after 250 ->
93+
ok
94+
end,
95+
receive
96+
hello -> ok
97+
after 10000 ->
98+
{error, timeout}
99+
end.
100+
101+
test_send_after_3() ->
102+
Self = self(),
103+
{ok, TRef} = timer:send_after(500, Self, hello_dest),
104+
ok = etest:assert_true(is_reference(TRef)),
105+
receive
106+
hello_dest -> {error, too_early}
107+
after 250 ->
108+
ok
109+
end,
110+
receive
111+
hello_dest -> ok
112+
after 10000 ->
113+
{error, timeout}
114+
end.
115+
116+
test_apply_after() ->
117+
Self = self(),
118+
{ok, TRef} = timer:apply_after(500, erlang, send, [Self, apply_result]),
119+
ok = etest:assert_true(is_reference(TRef)),
120+
receive
121+
apply_result -> {error, too_early}
122+
after 250 ->
123+
ok
124+
end,
125+
receive
126+
apply_result -> ok
127+
after 10000 ->
128+
{error, timeout}
129+
end.

0 commit comments

Comments
 (0)