Last active
December 16, 2016 02:11
-
-
Save noisesmith/3d97d7f9f3fddd4daaa5e1e01f795af7 to your computer and use it in GitHub Desktop.
acts like a future, but has a time-out after which it fails on deref
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns condor.future-timeout | |
(:require [clojure.core.async :as >]) | |
(:import (java.util Date) | |
(java.util.concurrent CancellationException))) | |
(defn timestamp | |
[] | |
(.getTime (Date.))) | |
(defn timed-future-call | |
"starts a future immediately, can declare it a failure based on elapsed time | |
f: called as a function, immediately with no arguments | |
time-out: milliseconds until failure, defaults to 0 | |
failure: callback which is provided the actual elapsed time in milliseconds | |
reference for which methods can be cancelled: https://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html#interrupt()" | |
([f] (timed-future-call f 0 (fn [_]))) | |
([f time-out] (timed-future-call f time-out (fn [_]))) | |
([f time-out failure] | |
(let [result (promise) | |
started (timestamp) | |
future-thread (future-call | |
(fn cancellable-call [] | |
(try (let [value (f)] | |
(deliver result value)) | |
(catch CancellationException _) | |
(finally | |
(let [value (failure (- (timestamp) started))] | |
(deliver result value))))))] | |
(>/go | |
(>/<! (>/timeout time-out)) | |
(future-cancel future-thread)) | |
result))) | |
(defmacro timed-future | |
" | |
user=> (time (frequencies | |
(map deref | |
(doall (repeatedly | |
10000 | |
#(f/timed-future {:time-out 1000 | |
:failure (constantly :times-up)} | |
(do (Thread/sleep 1000) | |
42))))))) | |
\"Elapsed time: 1902.66766 msecs\" | |
{42 8894, :times-up 1106}" | |
([form] `(timed-future {} ~form)) | |
([opts form] | |
{:pre [(map? opts)]} | |
(let [failure (or (:failure opts) (fn [_])) | |
time-out (or (:time-out opts) 0)] | |
`(timed-future-call (fn [] ~form) | |
~time-out | |
~failure)))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment