Yeah, I'm new to clojure, but your code seems a tad wonky. I just gave
dining philosophers a shot in clojure, and it was 32 non-empty non-
comment lines (though the printing blocks are non-atomic, so the
printout, while readable, is slightly bizarre at moments).

Okay, the first thing I have to say is that the way you are managing
state is not completely clear. Why is the table a ref containing other
refs? There isn't a need for so much indirection, and it might slow
down concurrency significantly (although I can't figure out exactly
where the concurrency comes from in your example). I'm not sure why
you are keeping track of so many things -- the way I heard the problem
didn't involve all the different elements you have. You also are using
thread sleeps to wait for events to happen, i.e. philosophers
finishing. In mine, the philosophers are threads, and I just join them
all, which is the proper way to do it (i.e. still works on super duper
slow computers).

loop_count is mental, talking about clojure style. A more idiomatic
way would be (dotimes [i 5] ...), or even more idiomatically, (dotimes
[_ 5] ...), because you don't use the variable. In my version, you
should have a method that is eat, not try eating, because you want
refs to manage some of the failure retry stuff.

And I agree with Laurent's comments. I hope this didn't come across as
super-harsh, I didn't mean it that way.

Here's my code, hopefully it can give you some ideas:

(def num-philos 5)
(def r (java.util.Random.))
(def max-wait 1000)
(defn wait [n] (. Thread (sleep n)))
(defn random-wait []  (wait (.nextInt r max-wait)))

(def forks (for [i (range num-philos)] (ref true)))
(def satisfied (for [i (range num-philos)] (ref false)))

(defn eat [i]
  (random-wait)
  (if (and @(nth forks (mod (dec i) num-philos)) @(nth forks i))
    (dosync (ref-set (nth forks (mod (dec i) num-philos)) false)
            (ref-set (nth forks i) false))
    (eat i)))

(defn finish-eating [i]
  (dosync (random-wait)
          (ref-set (nth forks (mod (dec i) num-philos)) true)
          (ref-set (nth forks i) true)
          (ref-set (nth satisfied i) true)))

(defn print-table-status []
  (print "Forks available:" (map deref forks) "\n")
  (print "Philosophers satisfied: " (map deref satisfied) "\n"))

(defn philo-eat [i] ;; not a transaction, so they happen
independently! :)
  (print-table-status)
  (print "Philosopher " i " trying to eat!\n")
  (eat i)
  (print "Philosopher " i " eating!\n")
  (random-wait)
  (finish-eating i)
  (print "Philosopher " i "done eating!\n")
  (print-table-status))

(def t (for [philo (range num-philos)] (Thread. #(philo-eat philo))))
(doall (map #(.start %) t))
(doall (map #(.join %) t))

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Reply via email to