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. You are right about impossibility of using alts! in the producer code to check if the chan can be written to before computing the value. I forgot alts! is a function, not a macro, and you can't pass expressions to it to be evaluated when the chan becomes available to write. Your last sample seems an useful way to manage simple stateless single-value producers from the consumer, but producers can be long-running go-blocks with their own state and with channels to other services, so I think is a little off base the original question. Saludos, Nahuel Greco. On Thu, Oct 9, 2014 at 4:16 PM, Leon Grapenthin <grapenthinl...@gmail.com> wrote: > On Thursday, October 9, 2014 2:22:50 PM UTC+2, Nahuel Greco wrote: >> >> 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. >> > > You can avoid this very easily. Everytime before the producer expensively > calculates its next value to put it on the channel, make it put a cheaply > calculated value, e. g. the keyword :useless, on the channel instead. > > Now on the consumer side you can do this: > > 0. Blocking (immediate take): Consume the keyword :useless = The producer > will begin production > 1. *This is what you want from peek! *Blocking take = Waiting for the > producer to have produced the expensive value, consume it *but the > producer won't calculate the next value (because he puts the :useless > keyword which won't be consumed until later)* > 2. Wait for external service to be ready, put value there > 3. Go to step 1 trigger production of the next value > > Assuming the producer and the consumer run on different threads, what have > you won by introducing step 0? > > 1. The producer thread can't begin to work until the consumer thread did > his work > 2. The consumer thread can't begin to work until the producer thread did > his work > > = At every point in time only one thread performs. Entirely :useless > multi-threading. > > I can also use alts! on the producer to check if he can write to the >> channel before computing the value, [...] >> > You can't > > > >> [...] >> > > >> 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). >> > > If I understand you right, you would want to start production of multiple > values in parallel, wait for the first to be ready, then put that to the > external service and loop. Here core.async can be of help. E. g. > (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)))))) > > > > Again, no peek required. > > >> >> >> >> Saludos, >> Nahuel Greco. >> >> On Thu, Oct 9, 2014 at 9:07 AM, Fergal Byrne <fergalby...@gmail.com> >> wrote: >> >>> Hi Nahuel, >>> >>> I think it's worth stepping back from discussing solutions and have a >>> look at the problem. If I'm reading things right you need the following: >>> >>> 1. Producer produces values one at a time - should not step until last >>> value has been handled correctly elsewhere. >>> 2. Middleman needs to consume one value and (potentially) retry an >>> external service until it can verify correct handling. >>> 3. Producer should not interpret the consumption of a value as a signal >>> to proceed. >>> >>> You also seem to want the following: >>> >>> a. Use core.async >>> b. Make the solution "elegant" >>> >>> That's all fine, but it seems like a bit of a golden hammer. Your >>> problem is precisely not the kind of problem core.async channels are >>> designed to solve. Channels are there to provide decoupling of producer and >>> consumer, whereas you, in fact, need the kind of coupling provide by >>> function calls. >>> >>> Channels are for when you don't want to know how or when your product is >>> handled. You're finished, you throw the product on a channel, and you move >>> on to making your next product. All you ever find out is if/that your >>> product has been picked off the channel. >>> >>> Function calls are for when you do need to know what happened to your >>> product, and when it has all happened, because you can't move on until the >>> last thing has been done. >>> >>> Just call the middleman in synchronous code in your producer, with one >>> value, and look at its return value to tell you what to do next. You get >>> your blocking semantics (1-3) and you also get information about success or >>> failure. >>> >>> Using channels, consumption is the only information the producer hears >>> back. To tell the producer you've completed your mission as middleman, >>> you'll need another channel. If you really want to use core.async: >>> >>> (>! c v) ; blocks until consumed >>> (respond-to (<! ackchan)) ; blocks until handled >>> ...do expensive stuff >>> >>> but this is just an expensive function call. >>> >>> Regards, >>> >>> Fergal Byrne >>> >>> >>> On Thu, Oct 9, 2014 at 11:16 AM, Eduard Bondarenko <edb...@gmail.com> >>> wrote: >>> >>>> I think the point is to not generate values by producer if external >>>> service is not available >>>> "The producer only unparks when the value is effectively consumed by >>>> the external service. That's my objective." >>>> >>>> "external ready" channel here serves as a latch that stops producer >>>> generating value. >>>> >>>> On Thu, Oct 9, 2014 at 6:39 AM, Fluid Dynamics <a209...@trbvm.com> >>>> wrote: >>>> > On Monday, October 6, 2014 9:36:59 AM UTC-4, edbond wrote: >>>> >> >>>> >> 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" chan >>>> >> >>>> >> client: >>>> >> - contact external server, put in "external ready" if ok >>>> >> - read from "outgoing" chan >>>> >> - send to external >>>> >> >>>> >> Handle exceptions and loop where you need. >>>> > >>>> > >>>> > If you're not reading from "outgoing" until the external server is >>>> known to >>>> > be ready, you don't need the "external ready" channel. Backpressure >>>> on the >>>> > "outgoing" channel will suffice to keep the producer from overrunning >>>> the >>>> > consumer in this case. >>>> > >>>> > -- >>>> > 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 a topic in the >>>> > Google Groups "Clojure" group. >>>> > To unsubscribe from this topic, visit >>>> > https://groups.google.com/d/topic/clojure/QbiwXYDw6oA/unsubscribe. >>>> > To unsubscribe from this group and all its topics, send an email to >>>> > clojure+u...@googlegroups.com. >>>> > For more options, visit https://groups.google.com/d/optout. >>>> >>>> -- >>>> 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. >>>> >>> >>> >>> >>> -- >>> >>> Fergal Byrne, Brenter IT >>> >>> http://inbits.com - Better Living through Thoughtful Technology >>> http://ie.linkedin.com/in/fergbyrne/ - https://github.com/fergalbyrne >>> >>> Founder of Clortex: HTM in Clojure - https://github.com/nupic- >>> community/clortex >>> >>> Author, Real Machine Intelligence with Clortex and NuPIC >>> Read for free or buy the book at https://leanpub.com/realsmartmachines >>> >>> Speaking on Clortex and HTM/CLA at euroClojure Krakow, June 2014: >>> http://euroclojure.com/2014/ >>> and at LambdaJam Chicago, July 2014: http://www.lambdajam.com >>> >>> e:fergalby...@gmail.com t:+353 83 4214179 >>> Join the quest for Machine Intelligence at http://numenta.org >>> Formerly of Adnet edi...@adnet.ie http://www.adnet.ie >>> >>> -- >>> 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. >>> >> >> -- > 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/d/optout. > -- 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/d/optout.