<div dir="ltr"><div><div><div><div><div><div><div><div><div><div><div><div><div><div>Here is the crux of what you are toying with: Erlang has two kinds of timeouts: idle timeouts and point-in-time timeouts. The timeouts you can set in a gen_server are idle timeouts, so they are implemented basically as<br><br></div>receive<br>  ...<br></div>after Timeout -><br>  ...<br></div>end<br><br></div>What this means is that any message which arrives in the mailbox cancels the timeout. In particular, your sys:get_state/1 call invokes such a message, resetting the timeout. If you want a point-in-time timeout, there is another tool for this: erlang:send_after/3. It will deliver a message through another timer system and even if the process is active, you will get the timer in a relatively timely fashion. You are not guaranteed to get the timer precisely at the point if the system is heavily loaded, but usually you get it within a couple of ms of where you want at worst. This is the essence of being soft-realtime, amont other things.<br><br></div>The gen_server timeouts are nice to use for the situation where idling means you can do some janitorial work in your process or do a hibernation. I often have some janitorial work that runs either on a counter (every 100 message) and also on an idle timer (20 seconds has passed with no message).<br></div></div></div></div></div></div></div></div></div></div><br><div class="gmail_quote"><div dir="ltr">On Fri, Jun 2, 2017 at 11:09 AM Ben Murphy <<a href="mailto:benmmurphy@gmail.com">benmmurphy@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">So a bunch of gen_server:* methods allow you to return a timeout<br>
value. So if you were thinking about how this would be implemented you<br>
would expect if elapsed time >Timeout it would send a timeout message<br>
to your process. This is true. However, if elapsed time > much greater<br>
than Timeout then a timeout message could be sent to your process :/<br>
How is this possible?<br>
<br>
If your process receives a system message before the timeout then the<br>
timeout is reset without considering how long you have waited before<br>
receiving a system message. For example: you could be waiting 1 month<br>
for a timeout then after 20 days someone did sys:get_state on your<br>
process then you are waiting another 1 month for your timeout..<br>
<br>
-module(wtf).<br>
-behaviour(gen_server).<br>
<br>
-export([init/1, code_change/3, handle_call/3, handle_cast/2,<br>
handle_info/2, terminate/2]).<br>
<br>
init(_Args) -><br>
  TS = erlang:timestamp(),<br>
  io:format("init: ~p~n", [TS]),<br>
  {ok, TS, 30 * 1000}.<br>
<br>
<br>
handle_info(Message, TS) -><br>
  io:format(user, "handle info :~p ~p ~n", [Message, erlang:timestamp()]),<br>
  Now = erlang:timestamp(),<br>
  io:format(user, "difference: ~p ~n", [timer:now_diff(Now, TS)]),<br>
  {noreply, TS}.<br>
<br>
<br>
code_change(_1, _2, _3) -><br>
  throw(wtf).<br>
handle_call(_1, _2, _3) -><br>
  throw(wtf).<br>
handle_cast(_1, _2) -><br>
  throw(wtf).<br>
terminate(_1, _2) -><br>
   ok.<br>
<br>
Erlang/OTP 19 [erts-8.0] [source] [64-bit] [smp:4:4]<br>
[async-threads:10] [hipe] [kernel-poll:false]<br>
<br>
Eshell V8.0  (abort with ^G)<br>
1> {ok, Pid} =  gen_server:start_link(wtf, [], []).<br>
init: {1496,394234,956218}<br>
{ok,<0.59.0>}<br>
2> sys:get_state(Pid).<br>
{1496,394234,956218}<br>
3> handle info :timeout {1496,394279,244306}<br>
difference: 44288466<br>
_______________________________________________<br>
erlang-questions mailing list<br>
<a href="mailto:erlang-questions@erlang.org" target="_blank">erlang-questions@erlang.org</a><br>
<a href="http://erlang.org/mailman/listinfo/erlang-questions" rel="noreferrer" target="_blank">http://erlang.org/mailman/listinfo/erlang-questions</a><br>
</blockquote></div>