A few thoughts on ways to improve this code: Using agents and go blocks in the same code is a bit odd. If you need a queue plus a process, just do something like this:
(defn faux-agent [c] (go (loop [] (when-let [msg (<! c)] ...do something... (recur))))) This go block will automatically terminate once the input channel is closed. Now you have code that is almost like an agent, but works well with channels (including back-pressure). Also, instead of having a public req channel and a response channel, consider using higher-order channels. Yes, you can send channels via channels. So instead of having a request look like this: (>! req-chan :req) do something like this: (>! req-chan [file-name my-response-channel]) (<! my-response-channel) This allows many processes to make requests and your code will end up a little easier to reason about. Just some thoughts. Timothy Baldridge On Mon, Jul 8, 2013 at 12:05 AM, vemv <v...@vemv.net> wrote: > As you can read here: > http://martintrojer.github.io/clojure/2013/07/07/coreasync-and-blocking-iodoing > blocking IO in a go block should be avoided. So I was thinking that > an alternative to non-blocking IO APIs is using agents and channels. > > The following sample program intends to illustrate the technique: > > (require '[clojure.core.async :as async :refer :all]) > (import '[java.util.concurrent Executors]) > > (spit "bar" (apply str (shuffle (range 100)))) > > (def slurper (agent nil)) > > (def spitter (agent nil)) > > (def max-concurrency 1) > > ;; when a go block wants to slurp a file, it communicates it by writing to > thins channel > (def slurping-request (chan max-concurrency)) > > ;; where requested slurped content gets served > (def slurps (chan max-concurrency)) > > (def rw-pool (Executors/newFixedThreadPool max-concurrency)) > > (def serving > (future > (while (<!! slurping-request) > (send-via rw-pool slurper (fn [_] (>!! slurps (seq (slurp "bar"))) > _))))) > > (go (while true > (>! slurping-request :req) > (let [old (<! slurps) > new (apply str (shuffle old))] > (send-via rw-pool spitter (fn [_] (spit "bar" new)))))) > > It is supposed to constantly modify a file, until you (close! > slurping-request). However, somehow nil-related issues crept in: > > > - With max-concurrency set to 1, at times an empty string gets written > to the file. > - With max-concurrency set to 4, the spitter agent fails. > > > What is going on? Maybe files need locking? Or am I misunderstanding some > aspect of core.async itself? > > -- > -- > 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. > > > -- “One of the main causes of the fall of the Roman Empire was that–lacking zero–they had no way to indicate successful termination of their C programs.” (Robert Firth) -- -- 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.