Skip to content

Commit

Permalink
Modernize and improve the timer module
Browse files Browse the repository at this point in the history
Remove most of the timer management overhead from the single
timer server process, and decentralize the actual process of
timing, to make the timer server more efficient and less prone
to becoming overloaded. The outward behavior of the timer
module is unchanged.

- Start the timer server under kernel_sup instead of
  kernel_safe_sup.

- Move argument validations out of the timer server and
  into the API functions.

- One-shot send timers are using erlang:send_after and
  erlang:cancel_timer in the client process, without going
  through the timer server, when the destination is a pid
  on the local node.

- The timer server does not do any actual timing any more but
  only executes actions and reschedules interval timers.
  Instead, erlang:start_timer is used for the timing.

- The timer table is not named any more, an ets:tid()
  is carried in a state variable instead.

- Processes related to interval timers are monitored (vs linked)
  by the timer server in order to cancel them when the related
  process dies.

- timer:sleep/1 now accepts arbitrarily high integer values.
  Integer values above the limit of what is allowed in the after
  clause of a receive expression are split up.

- Document that send_after and send_interval accept {RegName, Node}
  as message destinations.

- The function get_status/0 that was only used in tests has been removed,
  the tests now use sys:get_state instead.

- Test return values.
  • Loading branch information
Maria-12648430 authored and bjorng committed Jun 9, 2021
1 parent cf587ca commit 06cacbc
Show file tree
Hide file tree
Showing 5 changed files with 681 additions and 387 deletions.
33 changes: 21 additions & 12 deletions lib/stdlib/doc/src/timer.xml
Expand Up @@ -50,7 +50,9 @@
<p>Creating timers using
<seemfa marker="erts:erlang#send_after/3">erlang:send_after/3</seemfa> and
<seemfa marker="erts:erlang#start_timer/3">erlang:start_timer/3</seemfa>
is much more efficient than using the timers provided by this module. See
is more efficient than using the timers provided by this module. However,
the timer module has been improved in OTP 25, making it more efficient and
less susceptible to being overloaded. See
<seeguide marker="system/efficiency_guide:commoncaveats#timer-module">the
Timer Module section in the Efficiency Guide</seeguide>.</p>
</description>
Expand Down Expand Up @@ -116,8 +118,9 @@
<c>exit_after(<anno>Time</anno>, self(),
<anno>Reason1</anno>)</c>.</p>
<p><c>exit_after/3</c> sends an exit signal with reason
<c><anno>Reason1</anno></c> to
pid <c><anno>Pid</anno></c>. Returns <c>{ok, <anno>TRef</anno>}</c>
<c><anno>Reason1</anno></c> to <c><anno>Target</anno></c>,
which can be a local process identifier or an atom of a registered
name. Returns <c>{ok, <anno>TRef</anno>}</c>
or <c>{error, <anno>Reason2</anno>}</c>.</p>
</desc>
</func>
Expand Down Expand Up @@ -149,7 +152,7 @@
<p><c>kill_after/1</c> is the same as
<c>exit_after(<anno>Time</anno>, self(), kill)</c>.</p>
<p><c>kill_after/2</c> is the same as
<c>exit_after(<anno>Time</anno>, <anno>Pid</anno>, kill)</c>.</p>
<c>exit_after(<anno>Time</anno>, <anno>Target</anno>, kill)</c>.</p>
</desc>
</func>

Expand Down Expand Up @@ -190,15 +193,16 @@
<func>
<name name="send_after" arity="2" since=""/>
<name name="send_after" arity="3" since=""/>
<fsummary>Send <c>Message</c> to <c>Pid</c> after a specified
<fsummary>Send <c>Message</c> to <c>Destination</c> after a specified
<c>Time</c>.</fsummary>
<desc>
<taglist>
<tag><c>send_after/3</c></tag>
<item>
<p>Evaluates <c><anno>Pid</anno> ! <anno>Message</anno></c> after
<c><anno>Time</anno></c> milliseconds. (<c><anno>Pid</anno></c>
can also be an atom of a registered name.)</p>
<p>Evaluates <c><anno>Destination</anno> ! <anno>Message</anno></c> after
<c><anno>Time</anno></c> milliseconds. (<c><anno>Destination</anno></c> can
be a remote or local process identifier, an atom of a registered name or
a tuple <c>{RegName, Node}</c> for a registered name at another node.)</p>
<p>Returns <c>{ok, <anno>TRef</anno>}</c> or
<c>{error, <anno>Reason</anno>}</c>.</p>
<p>See also
Expand All @@ -223,10 +227,11 @@
<taglist>
<tag><c>send_interval/3</c></tag>
<item>
<p>Evaluates <c><anno>Pid</anno> ! <anno>Message</anno></c>
<p>Evaluates <c><anno>Destination</anno> ! <anno>Message</anno></c>
repeatedly after <c><anno>Time</anno></c> milliseconds.
(<c><anno>Pid</anno></c> can also be
an atom of a registered name.)</p>
(<c><anno>Destination</anno></c> can be a remote or local process
identifier, an atom of a registered name or a tuple <c>{RegName, Node}</c>
for a registered name at another node.)</p>
<p>Returns <c>{ok, <anno>TRef</anno>}</c> or
<c>{error, <anno>Reason</anno>}</c>.</p>
</item>
Expand All @@ -249,6 +254,11 @@
or suspends the process forever if <c><anno>Time</anno></c> is the
atom <c>infinity</c>. Naturally, this
function does <em>not</em> return immediately.</p>
<note>
<p>Before OTP 25, <c>timer:sleep/1</c> did not accept integer
timeout values greater than <c>16#ffffffff</c>, that is, <c>2^32-1</c>.
Since OTP 25, arbitrarily high integer values are accepted.</p>
</note>
</desc>
</func>

Expand Down Expand Up @@ -350,4 +360,3 @@ timer:cancel(R),
<seemfa marker="#cancel/1"><c>cancel/1</c></seemfa>.</p>
</section>
</erlref>

0 comments on commit 06cacbc

Please sign in to comment.