Понимание этого кода Clojure - PullRequest
4 голосов
/ 11 ноября 2011

Я очень плохо знаком с Clojure, и я изо всех сил пытался реализовать некоторый параллельный код. Я нашел этот код в Интернете. Есть предупреждение, что в Clojure нельзя использовать параллелизм, но я все равно хочу понять этот код.

(def *readers* (map #(agent %) '("one" "two" "three")))
(def *writers* (map #(agent %) '("four" "five")))
(def *mutex* (agent :unlocked))
(def *value* 0)

; mutex implementation
(defn lock [state who success-fn fail-fn]
  (send who (if (= state :locked) fail-fn success-fn))
  :locked)

(defn unlock [mutex]
  :unlocked)

; Must be invoked with send-off since this handler blocks
(defn rand-sleep [state next-fn]
  (Thread/sleep (rand-int 5))
  (send *agent* next-fn)
  state)

; Reader functions
(declare try-read)

(defn reader-got-lock [name]
  (println (format "Thread %s says that the value is %d." name *value*))
  (send *mutex* unlock)
  (send-off *agent* rand-sleep try-read)
  name)

(defn reader-did-not-get-lock [name]
  (println (format "Thread %s tried to read the value, but could not." name))
  (send-off *agent* rand-sleep try-read)
  name)

(defn try-read [name]
  (send *mutex* lock *agent* reader-got-lock reader-did-not-get-lock)
  name)

; Writer functions
(declare try-write)

(defn writer-got-lock [name]
  (println (format "Thread %s is taking the lock." name))
  (def *value* (rand-int 10))
  (println (format "Thread %s is changing the value to %d." name *value*))
  (send *mutex* unlock)
  (println (format "Thread %s is relasing the lock." name))
  (send-off *agent* rand-sleep try-write)
  name)

(defn writer-did-not-get-lock [name]
  (println (format "Thread %s tried to write the value, but could not." name))
  (send-off *agent* rand-sleep try-write)
  name)

(defn try-write [name]
  (send *mutex* lock *agent* writer-got-lock writer-did-not-get-lock)
  name)

(dorun (map #(send % try-write) *writers*))
(dorun (map #(send % try-read) *readers*))

В частности, я застрял в этой строке:

(defn try-write [name]
  (send *mutex* lock *agent* writer-got-lock writer-did-not-get-lock)
  name)

Он должен заблокировать мьютекс и вызвать либо писатель-получил-блокировку, либо писатель-не-получить-блокировку в зависимости от состояния мьютексов. Но где объявлено *agent* или это быстрый доступ к текущему агенту? Тогда как state передается в замок, это *agent* в случае вышеуказанного вызова или *agent* это who?

1 Ответ

5 голосов
/ 11 ноября 2011

*agent* является сокращением для текущего агента и неявно предоставляется clojure.*agent* передается как who.Последний звонок выглядит примерно так:

(lock @*mutex* *agent* writer-got-lock writer-did-not-get-lock)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...