+(ns scheduled-agent (:import java.util.concurrent.Executors java.util.concurrent.TimeUnit) (:use clojure.stacktrace)) ; This is starting to get less agent-like (defn- runnable-proxy [f] (proxy [Runnable] [] (run [] (f)))) (defn scheduled-agent [func period init] (let [pool (Executors/newScheduledThreadPool 1) data (ref init) pfunc (runnable-proxy (fn [] (try (let [val (func)] (dosync (ref-set data val))) (catch Exception e (print-stack-trace e 5)))))] {:pool pool :data data :future (ref nil) :func func :pfunc pfunc :period period :init init})) (defn poll [{d :data}] "Return current contents of agent." @d) (defn start! [{f :future pfunc :pfunc period :period pool :pool}] (dosync (if (nil? (ensure f)) (ref-set f (.scheduleWithFixedDelay pool pfunc 0 period TimeUnit/SECONDS))))) (defn cancel! [{f :future}] "Cancel automatic updating of agent data. Cannot be restarted." (if @f (.cancel @f false))) (defn update! [{func :func data :data}] "Synchronously update contents of agent." (let [val (func)] (dosync (ref-set data val))))