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.


Reply via email to