--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clo...@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+u...@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+u...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
I was thinking in a single-consumer scenario with a buffered chan, in which you want to check if you can consume the value before effectively consuming it. As you said, a peek operation has no sense if the channel has multiple consumers.
--
Picture the following:
producer ---> go-loop ---> external service
1- The producer puts a value to a unbuffered (chan) by doing (>! c v)
2- The go-loop consumes the value with a take operation, **unblocking** the producer
3- The go-loop contacts the external-service but the external service answers it can't process the value yet
4- The go-loop waits some timeout to retry the request to the external service
After step 2 the producer continues to compute (suppose an expensive computing) a new value but the previous one wasn't effectively consumed by the external service.
I don't want that, I want to enforce an end-to-end flow-control setup where the producer blocks on (>! c v) (the step 1) until the value is consumed by all parties,
Maybe not, maybe you want to reserve the cpu cycles for other tasks, or the producer needs a confirmation for other purposes before computing or requesting the value from another party. This is a simplified and distilled scenario.
No reservation, the ack solution works, but 1- I think the producer code can be simplified with the peek operation and 2- I want to know is there is a fudamental limitation in chans design/implementation prohibiting adding a peek operation.
Maybe not, maybe you want to reserve the cpu cycles for other tasks, or the producer needs a confirmation for other purposes before computing or requesting the value from another party. This is a simplified and distilled scenario.
Add one more chan, "external ready".Put :ok there to let producer generate new value.producer:- read from "external ready"- generate value- put into "outgoing" chanclient:- contact external server, put in "external ready" if ok- read from "outgoing" chan- send to externalHandle exceptions and loop where you need.
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+u...@googlegroups.com.
Fluid: as you said, backpressure on the outgoing channel will be sufficient to avoid producer to overrun consumer (without using any extra ack-channel), but the producer will compute a new not-yet-used value before blocking on sending it to consumer. That's what I want to avoid.
I can also use alts! on the producer to check if he can write to the channel before computing the value, [...]
[...]
Fregal: If middleman is managing all the communication with the external service for *multiple* producers, then it can't be reduced to a simple synchronous function call from a producer, hence the necessity of core.async (the alternative is to descend to locks world).
(defn exp-calcs [] #{(a/thread calc-exp-val-1) (a/thread calc-exp-val-2) (a/thread calc-exp-val-3) (a/thread calc-exp-val-4) (a/thread calc-exp-val-5)
; ... })
(loop [chans (exp-calcs)] (let [[val ch] (a/alts!! (seq exp-calcs))] ;; wait for external service, put val there ;; also have the cancellation ch in chans and use it to guard the ;; following form (let [chans (disj chans ch)] (recur (if (seq chans) chans (exp-calcs))))))
Leon: your :useless example is equivalent to one using the hypothetical peek operation and to the ack-channel solution, but what you define as ":useless multithreading" because at one time only one thread is working, is a valid synchronization scenario and the one I was searching for. The objective here was not to max CPU usage with these two threads / go-blocks.
As I said in a previous mail "maybe you want to reserve the cpu cycles for other tasks, or the producer needs a confirmation for other purposes before computing or requesting the value from another party, this is a distilled example".
Also think the producer after sending the computed value and before sending the :useless signal can do other things, maybe contacting other services to pre-fetch data used in the next value.
Also the :useless example needs more code on the producer side than a simple (>! c v). Given there is no peek operation and the producer code must participate explicitly in the synchronization, I prefer the ack solution over the :useless one.