Re: [go-nuts] synchronise read from two channels
Yup I thin I was frying my brain on this - it also led to questions such as "if I read a worker from the channel and there ISNT a URL waiting how do I write back into the channel making it available - what if more than one go routine is reading from the channel... etc" I knew I was over complicating it I just couldnt see the forest for the trees! I assumed I wanted channels for the available and busy workers when really I wanted stacks. thanks for the in-depth discussion - in future I will sleep on it next time and come at it afresh :) (ironically I'd done exactly this before with stacks in an old project which is what gave me the lightbulb moment this morning) Thanks everyone! On Thursday, December 1, 2016 at 3:21:46 PM UTC, Jesper Louis Andersen wrote: > > On Wed, Nov 30, 2016 at 6:07 PM> wrote: > >> Hi, I'm having a bit of a slow day... I'm trying to synchronise two reads >> from two channels and can't get my fuzzy head round the problem. >> >> > Go doesn't have support for an (atomic) read from multiple channels at > once. There are other systems which can do this (JoCaml, join-calculus, > Concurrent ML, Haskell's STM, Reagents[0] in Scala, ...) > > However, as you found out, one can often rearrange the code base as to > avoid the problem. There is also the problem of more advanced > select-constructs not being free in the performance sense: atomic sync on > multiple channels tend to be rather expensive. > > One reason it isn't that simple to implement is to consider the following > (hypothetical) snippet: > > select { > case w := <-available && urlChan <- value: > ..BODY.. > } > } > > in which the atomic operation must simultaneously receive a message on the > 'available' channel and send a message on the 'urlChan' channel. And > further, since you introduced && to mean logical-and-between-channels, you > might as well introduce || to mean logical-or-between-channels. Once there, > you may want to introduce a new type > > event t > > for some type t alongside 'chan t'. Hence the expression (<-available) > becomes an expression of type 'event *worker' and now they can be composed > via && and ||. This means we can get rid of select since it is just an > expression which successively applies || to a slice of values. If we then > introduce an new statement, sync, which turns 'event t' into a 't', we are > done. And we have almost implemented the basis of Concurrent ML in the > process. > > In short, you could be opening a regular can of worms if you start > allowing for more complicated select-expressions. Hence the school of > keeping them relatively simple. > > [0] https://people.mpi-sws.org/~turon/reagents.pdf > -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: [go-nuts] synchronise read from two channels
On Wed, Nov 30, 2016 at 6:07 PMwrote: > Hi, I'm having a bit of a slow day... I'm trying to synchronise two reads > from two channels and can't get my fuzzy head round the problem. > > Go doesn't have support for an (atomic) read from multiple channels at once. There are other systems which can do this (JoCaml, join-calculus, Concurrent ML, Haskell's STM, Reagents[0] in Scala, ...) However, as you found out, one can often rearrange the code base as to avoid the problem. There is also the problem of more advanced select-constructs not being free in the performance sense: atomic sync on multiple channels tend to be rather expensive. One reason it isn't that simple to implement is to consider the following (hypothetical) snippet: select { case w := <-available && urlChan <- value: ..BODY.. } } in which the atomic operation must simultaneously receive a message on the 'available' channel and send a message on the 'urlChan' channel. And further, since you introduced && to mean logical-and-between-channels, you might as well introduce || to mean logical-or-between-channels. Once there, you may want to introduce a new type event t for some type t alongside 'chan t'. Hence the expression (<-available) becomes an expression of type 'event *worker' and now they can be composed via && and ||. This means we can get rid of select since it is just an expression which successively applies || to a slice of values. If we then introduce an new statement, sync, which turns 'event t' into a 't', we are done. And we have almost implemented the basis of Concurrent ML in the process. In short, you could be opening a regular can of worms if you start allowing for more complicated select-expressions. Hence the school of keeping them relatively simple. [0] https://people.mpi-sws.org/~turon/reagents.pdf -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: [go-nuts] synchronise read from two channels
It seems that you are fighting the helpful infrastructure, but I can’t be sure from what you’ve said. You can (presumably) just do this: For u := range streamOfUrls { For w := range availableWorkers { w.url = u activeWorkers <- w } } …but that is strange to me. Why not just have every worker loop for urls on its input channel: for I := 0; I < workers; i++ { go Worker(urlChannel) } : func Worker (uChan chan url) { for u:= range uChan { do work with u } } : for ...range of urls… { urlChan <- nextUrl } close(urlChan) // will terminate all workers after their last task is assigned From:on behalf of Date: Wednesday, November 30, 2016 at 9:07 AM To: golang-nuts Subject: [go-nuts] synchronise read from two channels Hi, I'm having a bit of a slow day... I'm trying to synchronise two reads from two channels and can't get my fuzzy head round the problem. I have a channel containing urls (which will be feed periodically by a named pipe by another program) and I have a cannel which consists of a pool of available workers. I'd like to synchronise these and put a worker into a third channel for active workers if there is a url in the channel and if there is an available worker. Ideally I'd be able to do something like: go func(urlChan <-chan *url.URL, availableWorkerChan <-chan *worker, activeWorkerChan chan<- *worker){ for { select{ case w := <-availableWorkerChan && w.Url = <-urlChan: activeWorkersChan <- w } } }(a, b, c) But obviously thats not right! Can anyone offer my tired brain a clue? Cheers! Ben -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+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 "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.