Skip to content

Instantly share code, notes, and snippets.

@christianromney
Created July 12, 2013 11:32
Show Gist options
  • Save christianromney/5983782 to your computer and use it in GitHub Desktop.
Save christianromney/5983782 to your computer and use it in GitHub Desktop.
(ns async.core
(:require [clojure.core.async :as async :refer :all])
(:gen-class))
;; Based on http://talks.golang.org/2012/concurrency.slide#30
;;
;; The Go semantics don't quite translate the same way to core.async
;; I've swapped the talk and wait channels so that each "boring"
;; goroutine creates its own _private_ wait channel / semaphore.
;;
;; The message broadcast channel can be shared because each message
;; contains a reference to the private wait channel of its originating
;; go routine. Since each goroutine blocks until it gets a signal
;; on its wait channel, order is restored.
(defrecord Message [text chan])
(defn boring
[talk msg]
(let [wait (chan)]
(go
(doseq [n (iterate inc 1)]
(let [m (->Message (str msg " " n) wait)]
(>! talk m))
(Thread/sleep (int (* 1000 (rand))))
(<! wait)))
talk))
(defn fan-in
"Allow whoever is ready to speak up"
[one two]
(let [c (chan)]
(go (while true
(>! c (<! one))))
(go (while true
(>! c (<! two))))
c))
(defn -main
"Experiment with core/async channels"
[& args]
(let [talk (chan)
c (fan-in (boring talk "Boring Joe ")
(boring talk "Boring Ann "))]
(dotimes [n 5]
(let [msg1 (<!! c)
msg2 (<!! c)]
(println (:text msg1))
(println (:text msg2))
(>!! (:chan msg1) true)
(>!! (:chan msg2) true))))
(println "You're both boring, I'm leaving."))
@ddeaguiar
Copy link

Not sure why your 'boring' function needs a 'talk' channel param. See my implementation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment