Created
April 5, 2012 01:04
-
-
Save pcsanwald/2307057 to your computer and use it in GitHub Desktop.
Sleeping Barber...
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
; 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