I\'m looking for a macro that will throw an exception if an expression takes longer than X seconds to complete.
I came across this thread recently while asking the same question. I wasn't completely satisfied with the answers given so I cobbled together an alternative solution. This solution will run your code in the current thread and spin of a future to interrupt it after a set timeout in ms.
(defn invoke-timeout [f timeout-ms]
(let [thr (Thread/currentThread)
fut (future (Thread/sleep timeout-ms)
(.interrupt thr))]
(try (f)
(catch InterruptedException e
(throw (TimeoutException. "Execution timed out!")))
(finally
(future-cancel fut)))))
(defmacro timeout [ms & body] `(invoke-timeout (fn [] ~@body) ~ms))
You would use it in your code like this:
(timeout 1000 your-code)
OR
(invoke-timeout #(your-code) 1000)
One caveat to keep in mind is that your-code
must not catch the InterruptedException
used to trigger the TimeoutException. I use this for testing and it works well.
See the Thread.interrupt()
javadoc for additional caveats.
You can see this code in use here.