[erlang-questions] max timeout

Per Hedeland per@REDACTED
Fri Aug 22 00:11:22 CEST 2008


Alpár Jüttner <alpar@REDACTED> wrote:
>
>As I recall, someone noted on that thread that timer:sleep() works well
>for arbitrarily large numbers.

I thought that might have been me:-( - but I see now that I just said
"the timer module" and gave an example using timer:send_after/2, so I
was almost right...

>Now I looked at the source and found that this is _not_ true. Strangely
>enough, all the functions of the timer modules seem to work correctly
>with large numbers _except_ timer:sleep() which has a definition as
>simple as this:
>
>sleep(T) ->
>    receive
>    after T -> ok
>    end.

Ouch. But no-one will ever need to sleep for 50 days or more, right?:-)

>It might be worth fixing.

And I guess I half-owe the fix - the problem is (as I discovered...)
that there may be (is) code, um, "out there", that relies on being able
to use timer:sleep/1 without having the timer_server running *or*
getting "auto-started". Below is what I believe to be a backwards-
compatible fix (against R12B-3), but it's pretty ugly - would probably
be better to e.g.  define a new function long_sleep/1 or somesuch for
the "unlimited" case.

--Per Hedeland

--- lib/stdlib/src/timer.erl.orig	2007-11-26 19:55:44.000000000 +0100
+++ lib/stdlib/src/timer.erl	2008-08-21 23:00:45.000000000 +0200
@@ -75,9 +75,14 @@
 cancel(BRef) ->
     req(cancel, BRef).
 
-sleep(T) ->
-    receive
-    after T -> ok
+sleep(Time) ->
+    case whereis(timer_server) of
+	undefined -> 
+	    receive
+	    after Time -> ok
+	    end;
+	_ ->
+	    req(sleep, Time)
     end.
 
 %%
@@ -176,6 +181,13 @@
 	    {reply, {error, badarg}, [], next_timeout()}
     end;
 
+handle_call({sleep, Time, Started}, From, Ts) ->
+    Req = {apply_after, {Time, {gen_server, reply, [From, ok]}}, Started},
+    case handle_call(Req, From, Ts) of
+        {reply, {ok, _}, _, Timeout} -> {noreply, [], Timeout};
+        Reply                        -> Reply
+    end;
+
 handle_call({cancel, BRef = {_Time, Ref}, _}, _From, Ts) 
                                            when is_reference(Ref) ->
     delete_ref(BRef),



More information about the erlang-questions mailing list