Skip to content

Instantly share code, notes, and snippets.

@cgrand
Created September 17, 2009 10:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cgrand/188441 to your computer and use it in GitHub Desktop.
Save cgrand/188441 to your computer and use it in GitHub Desktop.
(defn walk-out [customer]
(ref-set customer :outside))
(defn wait [customer {q :queue}]
(alter q conj customer)
(ref-set customer :waiting))
(defn sleeping? [barber]
(= :sleeping (ensure barber)))
(defn wake-up [barber]
(ref-set barber :awake))
(defn full? [{q :queue, max :max}]
(<= max (count (ensure q))))
(defn next-customer [{q :queue}]
(when-let [customer (peek (ensure q))]
(alter q pop)
customer))
(defn do-later [f]
(future
(Thread/sleep (+ 100 (rand-int 600)))
(dosync (f))))
(defn walk-in [shop customer]
(if (full? shop)
(do-later #(walk-in shop customer))
(let [barber (shop :barber)]
(when (sleeping? barber)
(wake-up barber))
(wait customer shop))))
(defn cut-hair-or-sleep [shop]
(if-let [customer (next-customer shop)]
(do
(ref-set (shop :barber) {:cutting-hair customer})
(ref-set customer :serviced)
(do-later
#(do
(ref-set customer :new-haircut)
(cut-hair-or-sleep shop))))
(ref-set (shop :barber) :sleeping)))
(defn add-log [ref s]
(add-watch ref :log
#(println s %4)))
(defn shop [n]
(let [shop {:barber (ref :sleeping)
:queue (ref clojure.lang.PersistentQueue/EMPTY)
:max n}]
(doto (shop :barber)
(add-log "barber")
(add-watch :react
(fn [_ _ _ state]
(when (= state :awake)
(dosync (cut-hair-or-sleep shop))))))
shop))
(defn customer [id]
(-> (ref :outside)
(add-log (str "customer " id))))
(let [shop (shop 3)]
(doseq [i (range 20)]
(future (dosync (walk-in shop (customer i))))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment