Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I create a constantly running background process in Clojure?

How can I create a constantly running background process in Clojure? Is using "future" with a loop that never ends the right way?

like image 853
yazz.com Avatar asked Dec 30 '10 06:12

yazz.com


2 Answers

You could just start a Thread with a function that runs forever.

(defn forever []
  ;; do stuff in a loop forever
)

(.start (Thread. forever))

If you don't want the background thread to block process exit, make sure to make it a daemon thread:

(doto 
   (Thread. forever)
   (.setDaemon true)
   (.start))

If you want some more finesse you can use the java.util.concurrent.Executors factory to create an ExecutorService. This makes it easy to create pools of threads, use custom thread factories, custom incoming queues, etc.

The claypoole lib wraps some of the work execution stuff up into a more clojure-friendly api if that's what you're angling towards.

like image 141
Alex Miller Avatar answered Sep 18 '22 14:09

Alex Miller


My simple higher-order infinite loop function (using futures):

(def counter (atom 1))

(defn infinite-loop [function]   
  (function)
  (future (infinite-loop function))
  nil) 

;; note the nil above is necessary to avoid overflowing the stack with futures...

(infinite-loop 
  #(do 
     (Thread/sleep 1000) 
     (swap! counter inc)))

;; wait half a minute....

@counter
=> 31

I strongly recommend using an atom or one of Clojures other reference types to store results (as per the counter in the example above).

With a bit of tweaking you could also use this approach to start/stop/pause the process in a thread-safe manner (e.g. test a flag to see if (function) should be executed in each iteration of the loop).

like image 28
mikera Avatar answered Sep 22 '22 14:09

mikera