Ben Kovitz
Ben Kovitz

Reputation: 5020

How do you kill a core.async/thread?

I've got some threads returned by core.async/thread involved in some process, which I'm about to shut down. I'm not shutting down my entire program, just these threads. How can I terminate the threads?

The .stop method of the Java Thread class is deprecated but I'd be happy to use it, except that core.async/thread returns not a Thread, but a ManyToManyChannel:

user=> (clojure.core.async/thread)
#object[clojure.core.async.impl.channels.ManyToManyChannel 0x780e97c0
  "clojure.core.async.impl.channels.ManyToManyChannel@780e97c0"]
user=> (type *1)
clojure.core.async.impl.channels.ManyToManyChannel

I haven't found any documentation on ManyToManyChannel. That sounds like a strange name for the type of a thread, so there might be something elementary here that I don't understand. But here's my current naïve, nonsensical-sounding question: How do you kill a ManyToManyChannel?

clojure.repl/thread-stopper seems to have no effect on ManyToManyChannels.

Upvotes: 4

Views: 1882

Answers (1)

Leon Grapenthin
Leon Grapenthin

Reputation: 9266

You let the thread terminate naturally. If external termination is necessary, you have to implement it.

(defn terminatable [input-ch terminate-ch]
   (thread
     (loop []
       (let [[v ch] (alts!! [input-ch terminate-ch])]
         (if (identical? ch input-ch)
           (if (some? v)
             (do (process-input v) (recur))
             ;; else input-ch has closed -> don't call recur,
             ;; thread terminates
             )
           ;; else we received sth. from terminate-ch,
           ;; or terminate-ch has closed -> don't call recur,
           ;; thread terminates
           )))))

Then terminate externally via (close! terminate-ch)

Finally you can determine when the thread is terminated by taking from the channel returned by thread.

I. e.

(take! (terminatable (chan) (doto (chan) close!)) 
       (fn [_] (println "Thread is terminated")))

Upvotes: 3

Related Questions