I have a top-level core.async go loop. I want it to run indefinitely, at least until I signal it to stop with CTRL-C or kill or similar. I'm currently using java.lang.Runtime/addShutdownHook like this:
(ns async-demo.core
(:require [clojure.core.async :as async
:refer [<! >! <!! timeout chan alt! go]]))
(defn run [] (go (loop [] (recur))))
(.addShutdownHook (Runtime/getRuntime) (Thread. #(println "SHUTDOWN")))
Here are my problems:
If I start the REPL and (run)
then it starts and runs in a background thread. When I exit the REPL, I don't see the desired shutdown message.
However, when I run from lein run
, the go loop exits immediately and displays "SHUTDOWN".
Neither is what I want.
I don't necessarily expect to find a solution that works for all JVM's. I develop on a Mac and deploy to Ubuntu, so I'd like to find a solution that works for both:
Mac JVM: java version "1.7.0_45" Java(TM) SE Runtime Environment (build 1.7.0_45-b18) Java HotSpot(TM) 64-Bit Server VM (build 24.45-b08, mixed mode)
Ubuntu JVM: java version "1.7.0_25" OpenJDK Runtime Environment (IcedTea 2.3.10) (7u25-2.3.10-1ubuntu0.12.04.2) OpenJDK 64-Bit Server VM (build 23.7-b01, mixed mode)
You can use a signalling exit-ch
and do a conditional to see if you should exit the loop. The channel + conditional is better handled in clojure by alt!:
(ns async-demo.core
(:require [clojure.core.async :refer [chan go-loop alt! timeout put!]]))
(defn run
[]
(let [exit-ch (chan)]
(go-loop []
(alt!
(timeout 10) (recur)
exit-ch nil
exit-ch
(let [exit-ch (run)]
(.addShutdownHook (Runtime/getRuntime) (put! exit-ch true)))
If you just close!
the channel, it won't stop the loop from running. Also, don't need to start a go block just to send a value to a channel.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With