Took me a while to get the idea but higher-order channels are brilliant - 
that way one ensures a given reply was actually targeted at one's request. 
Thanks for the suggestion!

Faux-agents would have the limitation of not being to (reasonably) perform 
blocking I/O - which is the point of my sample program.

An improved version:

(require '[clojure.core.async :as async :refer :all])
(import '[java.util.concurrent Executors]
        '[java.util.concurrent.locks ReentrantReadWriteLock])

(spit "bar" (apply str (shuffle (range 100))))

(def max-concurrency 4)

(def requests (chan max-concurrency))

;; only ensures exclusive access within the app - not across the OS
;; too lazy to use a FileLock :)
(def lock (ReentrantReadWriteLock.))

(def rw-pool (Executors/newFixedThreadPool max-concurrency))

;; one sends actions to anonymous one-off multiple agents
;; (as opposed to a single, named one), in order to increase concurrency

(dotimes [_ max-concurrency]
  (go (loop []
        (when-let [request (<! requests)]
          (send-via rw-pool (agent nil) (fn [_]
                                          (try
                                            (-> lock .readLock .lock)
                                            (>!! request (seq (slurp 
"bar")))
                                            (finally
                                              (-> lock .readLock 
.unlock)))))
          (recur)))))

(go (loop []
      (let [request (chan)
            _ (>! requests request)
            response (<! request)]
        (send-via rw-pool (agent nil) (fn [_]
                                        (try
                                          (-> lock .writeLock .lock)
                                          (spit "bar" (apply str (shuffle 
response)))
                                          (finally
                                            (-> lock .writeLock .unlock)))))
        (recur))))

As commented, locking is only partially useful (that's why opening the file 
might display an empty string at times). Also, don't know what would be the 
best way to indicate termination to the second go block...

-- 
-- 
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
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to