Skip to content

Instantly share code, notes, and snippets.

@pcsanwald
Created April 5, 2012 01:04
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 pcsanwald/2307057 to your computer and use it in GitHub Desktop.
Save pcsanwald/2307057 to your computer and use it in GitHub Desktop.
Sleeping Barber...
; declare a total variable which will keep
; count of the number of haircuts
(def total (agent 0))
; declare a queue for customer/barber:producer/consumer behavior
(def seats (ref (clojure.lang.PersistentQueue/EMPTY)))
; it takes 20ms to give a haircut.
; when a haircut is done, we'll
; safely increment the total.
(defn cut-hair [thetotal]
(dosync
(if (peek @seats)
(do
; alter must be called within a transaction
; alter <ref> <function> <args>
(alter seats pop)
(Thread/sleep 20)
(inc thetotal)
)
thetotal
)))
; if there are seats available in the lobby, sit down,
; otherwise, leave (which is a no-op)
(defn enter_lobby [customer]
(dosync
(if (< (count @seats) 3)
; conjoin returns a new collection with cusomter added
(alter seats conj customer)
)))
; this is the whole key to the program. adding a watch allows
; the barber to wake up when the reference to seats has been changed.
; the "send-to-barber" is a key, its only use is to remove the watch.
(add-watch seats :send-to-barber
(fn [_ _ _ _] (send total cut-hair)))
; run a test for 10 seconds
(def start (System/currentTimeMillis))
(println (format "starting with %s" @total))
; while 10 seconds has not passed since the start time
(while
(<= (- (System/currentTimeMillis) start) 10000)
; sleep at a random interval between 10 and 30
(Thread/sleep (nth (range 10 30) (rand-int 20)))
; it doesn't really matter what we send here, as long as it's
; an agent. the agent represents the customer entering the lobby here.
(send (agent :customer) enter_lobby)
)
(println (format "finished with %s in %d seconds" @total (- (System/currentTimeMillis) start)))
(remove-watch seats :send-to-barber)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment