with-timeout... ?

197 views
Skip to first unread message

Sean Allen

unread,
Mar 9, 2011, 7:12:26 AM3/9/11
to clo...@googlegroups.com
Yesterday I was writing a bit of code that needs to wait for an
external event to happen but if it doesn't happen with X amount of
time,
to timeout with an error.

Is there a library to handle this? I know you can do it with a future
and if you google the general idea, there are a few blog posts, stack
overflow questions etc that all have the same basic solution. It seems
like such a common thing to do that there would be a standard
function/macro out there for it rather than everyone rolling their
own. I couldn't however find one.

Does one exist? If yes, pointer in the right direction.

Thanks,
Sean

Baishampayan Ghose

unread,
Mar 9, 2011, 7:25:12 AM3/9/11
to clo...@googlegroups.com

You can roll your own macro to do this.

Example -

(defmacro with-timeout [ms & body]
`(let [f# (future ~@body)]
(.get #^java.util.concurrent.Future f# ~ms
java.util.concurrent.TimeUnit/MILLISECONDS)))

Regards,
BG

--
Baishampayan Ghose
b.ghose at gmail.com

Sean Allen

unread,
Mar 9, 2011, 7:43:29 AM3/9/11
to clo...@googlegroups.com, Baishampayan Ghose

Variation on that macro are what I've seen across the variety of sources
I've mentioned in my original message. It just strikes me as odd that something
so general hasn't made it into a library.

If it really hasn't made a library, ok.. I just wanted to make sure it
wasn't in a
library somewhere and that keeping the hand rolled macro wasn't something
I should still be doing.

Alan

unread,
Mar 9, 2011, 2:02:00 PM3/9/11
to Clojure
See https://github.com/Raynes/clojail

It's a sandboxing library for Clojure, which among other things means
it needs to try running an operation and give up after N seconds. You
can skip the sandboxing part entirely if you want; it exposes a pretty
general thunk-timeout function.

On Mar 9, 4:43 am, Sean Allen <s...@monkeysnatchbanana.com> wrote:

Seth

unread,
Mar 9, 2011, 5:55:14 PM3/9/11
to Clojure
Or you could just modify the source of promise ... i dont know why
promises dont support timeouts ....

(defprotocol PWait
(wait-for [this timeout units] [this timeout]))
;;copied from clojure source, but adding timeout wait-for
(defn promise
"Alpha - subject to change.
Returns a promise object that can be read with deref/@, and set,
once only, with deliver. Calls to deref/@ prior to delivery will
block. All subsequent derefs will return the same delivered value
without blocking."
{:added "1.1"}
[]
(let [d (java.util.concurrent.CountDownLatch. 1)
v (atom nil)]
(reify
clojure.lang.IDeref
(deref [_] (.await d) @v)
PWait
(wait-for [this timeout]
(wait-for this timeout
java.util.concurrent.TimeUnit/MILLISECONDS))
(wait-for [this timeout units]
(if timeout
(.await d timeout units)
(do (.await d) true)))
clojure.lang.IFn
(invoke [this x]
(locking d
(if (pos? (.getCount d))
(do (reset! v x)
(.countDown d)
x)
(throw
(IllegalStateException.
"Multiple deliver calls to a promise"))))))))

Stuart Sierra

unread,
Mar 9, 2011, 8:31:32 PM3/9/11
to clo...@googlegroups.com
I've been working in this direction with Cljque, for example http://bit.ly/gCtmAl

Cljque is still an experiment and has no stable API or documentation.

-Stuart Sierra

Seth

unread,
Mar 9, 2011, 11:11:53 PM3/9/11
to Clojure
oooh ... I can definitely find a use for this in my project! Thanks
for pointing it out.

Jeff Rose

unread,
Mar 10, 2011, 6:05:50 AM3/10/11
to Clojure
In Overtone we have the same situation, where we return a promise
representing a server response and sometimes we want to timeout if the
response never arrives. This is what we use:

(defn await-promise!
([prom] (await-promise prom REPLY-TIMEOUT))
([prom timeout]
(.get (future @prom) timeout TimeUnit/MILLISECONDS)))

(We have another version without the exclamation mark that
returns :timeout rather than throwing an exception when timed out.)

I agree with you though, that something along these lines should be
built-in. I was surprised to find that there was no way to block on a
promise with a timeout, as it seems like such a typical requirement
for almost anything you might be promised.

-Jeff

jweiss

unread,
Mar 10, 2011, 9:55:04 AM3/10/11
to Clojure
I wrote this macro a little while ago because I need that same
construct:

https://gist.github.com/701051
Reply all
Reply to author
Forward
0 new messages