Re: [go-nuts] Channels: selecting the last element

2018-12-18 Thread Chris Burkert
Thanks Robert,
Daves article is mind opening. I created 4 variants of my program to
compare the effects and to give others the chance to study it:

   1. https://play.golang.org/p/WE_CbRlfTFf
   2. https://play.golang.org/p/FnuzyEVHS-I
   3. https://play.golang.org/p/S9ssTxlZK6X
   4. https://play.golang.org/p/XHLGfjYUP17

For the moment I will go for the second variant with buffered and disabled
channels.
Thanks to all!

Am Di., 18. Dez. 2018 um 21:03 Uhr schrieb robert engels <
reng...@ix.netcom.com>:

> This may be a helpful read:
>
> https://dave.cheney.net/2013/04/30/curious-channels
>
> On Dec 18, 2018, at 2:02 PM, robert engels  wrote:
>
> To clarify the semantics aspects:
>
> If A cannot proceed until B performs it’s work, because there is a
> dependency, then using a unbuffered channel simplifies a lot - you will
> always be at most “one event ahead” without any extra synchronization (wait
> groups, etc.)
>
> On Dec 18, 2018, at 2:01 PM, robert engels  wrote:
>
> Whether to use buffered or unbuffered comes down to two things:
>
> 1) the semantics of the communication. because using unbuffered channels
> simplifies a lot - knowing the send will not complete until the read
> completes - it provides a synchronization mechanism between events/messages
> and routines.
>
> 2) performance… imagine the following pseudo code:
>
> routine A sends messages to routine B
> routine B's processing of messages is variable - sometimes very fast,
> sometimes very slow…
> --- for example, let B be a logger, that every once in a while needs
> to write to disk (the much slower operation)
>
> so if A is a low latency event processor - getting stuck trying to send to
> B would not be ideal - but since this only happens ‘rarely’ by using a
> buffered channel (with the size = number of events expected in a B “slow”
> time), you avoid “blocking” A
>
> for example, A is sending financial orders to an exchange - you would not
> want to every slow A down just because the logger was slow
>
> For the performance aspect, you are essentially increasing the
> parallelism, since any “block/wait” degrades this
>
> Hope that helps.
>
>
>
> On Dec 18, 2018, at 1:49 PM, Chris Burkert 
> wrote:
>
> Robert,
> it seems to me that you have a clear understanding about unbuffered vs.
> buffered channels. I feel unbuffered channels are safer to use especially
> in an acyclic directed graph of flowing values. Buffered channels seem to
> reduce blocking but I feel they come with the cost of such side effects
> like my initial problem of forgotten results in their channels. I would
> love to hear/read/see more on the unbuffered vs. buffered tradeoff to get
> rid of this gut feeling I am currently based on :-). Any good article you
> can point me to?
> Thanks
>
> Robert Engels  schrieb am Di. 18. Dez. 2018 um
> 17:03:
>
>> That code is incorrect as well when using buffered channels.
>>
>> On Dec 18, 2018, at 10:00 AM, Skip Tavakkolian <
>> skip.tavakkol...@gmail.com> wrote:
>>
>> why not just  drop the select? i think the following is guaranteed
>> because putting things on rc has to succeed before putting true into dc:
>>
>> package main
>>
>> import (
>> "fmt"
>> )
>>
>> func do(i int, rc chan<- int, dc chan<- bool) {
>> rc <- i
>> dc <- true
>> }
>>
>> func main() {
>> worker := 10
>> rc := make(chan int, worker)
>> done := 0
>> dc := make(chan bool, worker)
>> for i := 0; i < worker; i++ {
>> go do(i, rc, dc)
>> }
>> for done < worker {
>> r := <-rc
>> fmt.Println(r)
>> <-dc
>> done++
>> }
>> }
>>
>>
>> On Tue, Dec 18, 2018 at 5:35 AM Chris Burkert 
>> wrote:
>>
>>> Dear all,
>>>
>>> I have a couple of goroutines sending multiple results over a channel -
>>> a simple fan-in. They signal the completion on a done channel. Main selects
>>> on the results and done channel in parallel. As the select is random main
>>> sometimes misses to select the last result. What would be the idiomatic way
>>> to prevent this and completely drain the result channel?
>>>
>>> Here is a minmal example which sometimes prints one 0 but should always
>>> print two of them:
>>>
>>> package main
>>>
>>> import (
>>> "fmt"
>>> )
>>>
>>> func do(rc chan<- int, dc chan<- bool) {
>>> rc <- 0
>>> dc <- true
>>> }
>>>
>>> func main() {
>>> worker := 2
>>> rc := make(chan int, worker)
>>> done := 0
>>> dc := make(chan bool, worker)
>>> for i := 0; i < worker; i++ {
>>> go do(rc, dc)
>>> }
>>> for done < worker {
>>> select {
>>> case <-dc:
>>> done++
>>> case r := <-rc:
>>> fmt.Println(r)
>>> }
>>> }
>>> }
>>>
>>> many thanks
>>> Chris
>>>
>>> --
>>> 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 

Re: [go-nuts] Channels: selecting the last element

2018-12-18 Thread Chris Burkert
Now I got it - thanks for the explanation.

Am Mi., 19. Dez. 2018 um 02:25 Uhr schrieb :

> > feel unbuffered channels are safer to use especially in an acyclic
> directed graph of flowing values. Buffered channels seem to reduce blocking
> but I feel they come with the cost of such side effects like my initial
> problem of forgotten results in their channels.
>
>
> that happens with unbuffered channel too, if, for example, you mix it with
> a select on context cancellation.
> Maybe you are lucky and your data source provides a acknowledgment
> mechanism, maybe you are not and it s up to you to work around.
> This becomes a problem when the code can t be rationalized via an api that
> is able to wrap those behaviors.
>
> On Tuesday, December 18, 2018 at 8:50:20 PM UTC+1, Chris Burkert wrote:
>>
>> Robert,
>> it seems to me that you have a clear understanding about unbuffered vs.
>> buffered channels. I feel unbuffered channels are safer to use especially
>> in an acyclic directed graph of flowing values. Buffered channels seem to
>> reduce blocking but I feel they come with the cost of such side effects
>> like my initial problem of forgotten results in their channels. I would
>> love to hear/read/see more on the unbuffered vs. buffered tradeoff to get
>> rid of this gut feeling I am currently based on :-). Any good article you
>> can point me to?
>> Thanks
>>
>> Robert Engels  schrieb am Di. 18. Dez. 2018 um
>> 17:03:
>>
>>> That code is incorrect as well when using buffered channels.
>>>
>>> On Dec 18, 2018, at 10:00 AM, Skip Tavakkolian 
>>> wrote:
>>>
>>> why not just  drop the select? i think the following is guaranteed
>>> because putting things on rc has to succeed before putting true into dc:
>>>
>>> package main
>>>
>>> import (
>>> "fmt"
>>> )
>>>
>>> func do(i int, rc chan<- int, dc chan<- bool) {
>>> rc <- i
>>> dc <- true
>>> }
>>>
>>> func main() {
>>> worker := 10
>>> rc := make(chan int, worker)
>>> done := 0
>>> dc := make(chan bool, worker)
>>> for i := 0; i < worker; i++ {
>>> go do(i, rc, dc)
>>> }
>>> for done < worker {
>>> r := <-rc
>>> fmt.Println(r)
>>> <-dc
>>> done++
>>> }
>>> }
>>>
>>>
>>> On Tue, Dec 18, 2018 at 5:35 AM Chris Burkert 
>>> wrote:
>>>
 Dear all,

 I have a couple of goroutines sending multiple results over a channel -
 a simple fan-in. They signal the completion on a done channel. Main selects
 on the results and done channel in parallel. As the select is random main
 sometimes misses to select the last result. What would be the idiomatic way
 to prevent this and completely drain the result channel?

 Here is a minmal example which sometimes prints one 0 but should always
 print two of them:

 package main

 import (
 "fmt"
 )

 func do(rc chan<- int, dc chan<- bool) {
 rc <- 0
 dc <- true
 }

 func main() {
 worker := 2
 rc := make(chan int, worker)
 done := 0
 dc := make(chan bool, worker)
 for i := 0; i < worker; i++ {
 go do(rc, dc)
 }
 for done < worker {
 select {
 case <-dc:
 done++
 case r := <-rc:
 fmt.Println(r)
 }
 }
 }

 many thanks
 Chris

 --
 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...@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...@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.
>

-- 
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] Channels: selecting the last element

2018-12-18 Thread Michael Jones
Unbuffered channels are not dangerous. They just mean that “done sending”
is not the same as “done receiving.” I have done many variations of these
approaches and all work...but I’ve never used select.

On Tue, Dec 18, 2018 at 5:25 PM  wrote:

> > feel unbuffered channels are safer to use especially in an acyclic
> directed graph of flowing values. Buffered channels seem to reduce blocking
> but I feel they come with the cost of such side effects like my initial
> problem of forgotten results in their channels.
>
>
> that happens with unbuffered channel too, if, for example, you mix it with
> a select on context cancellation.
> Maybe you are lucky and your data source provides a acknowledgment
> mechanism, maybe you are not and it s up to you to work around.
> This becomes a problem when the code can t be rationalized via an api that
> is able to wrap those behaviors.
>
> On Tuesday, December 18, 2018 at 8:50:20 PM UTC+1, Chris Burkert wrote:
>>
>> Robert,
>> it seems to me that you have a clear understanding about unbuffered vs.
>> buffered channels. I feel unbuffered channels are safer to use especially
>> in an acyclic directed graph of flowing values. Buffered channels seem to
>> reduce blocking but I feel they come with the cost of such side effects
>> like my initial problem of forgotten results in their channels. I would
>> love to hear/read/see more on the unbuffered vs. buffered tradeoff to get
>> rid of this gut feeling I am currently based on :-). Any good article you
>> can point me to?
>> Thanks
>>
>> Robert Engels  schrieb am Di. 18. Dez. 2018 um
>> 17:03:
>>
>>> That code is incorrect as well when using buffered channels.
>>>
>>> On Dec 18, 2018, at 10:00 AM, Skip Tavakkolian 
>>> wrote:
>>>
>>> why not just  drop the select? i think the following is guaranteed
>>> because putting things on rc has to succeed before putting true into dc:
>>>
>>> package main
>>>
>>> import (
>>> "fmt"
>>> )
>>>
>>> func do(i int, rc chan<- int, dc chan<- bool) {
>>> rc <- i
>>> dc <- true
>>> }
>>>
>>> func main() {
>>> worker := 10
>>> rc := make(chan int, worker)
>>> done := 0
>>> dc := make(chan bool, worker)
>>> for i := 0; i < worker; i++ {
>>> go do(i, rc, dc)
>>> }
>>> for done < worker {
>>> r := <-rc
>>> fmt.Println(r)
>>> <-dc
>>> done++
>>> }
>>> }
>>>
>>>
>>> On Tue, Dec 18, 2018 at 5:35 AM Chris Burkert 
>>> wrote:
>>>
>>> Dear all,

 I have a couple of goroutines sending multiple results over a channel -
 a simple fan-in. They signal the completion on a done channel. Main selects
 on the results and done channel in parallel. As the select is random main
 sometimes misses to select the last result. What would be the idiomatic way
 to prevent this and completely drain the result channel?

 Here is a minmal example which sometimes prints one 0 but should always
 print two of them:

 package main

 import (
 "fmt"
 )

 func do(rc chan<- int, dc chan<- bool) {
 rc <- 0
 dc <- true
 }

 func main() {
 worker := 2
 rc := make(chan int, worker)
 done := 0
 dc := make(chan bool, worker)
 for i := 0; i < worker; i++ {
 go do(rc, dc)
 }
 for done < worker {
 select {
 case <-dc:
 done++
 case r := <-rc:
 fmt.Println(r)
 }
 }
 }

 many thanks
 Chris

 --
 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...@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...@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.
>
-- 

*Michael T. jonesmichael.jo...@gmail.com *

-- 
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] Channels: selecting the last element

2018-12-18 Thread mhhcbon
> feel unbuffered channels are safer to use especially in an acyclic 
directed graph of flowing values. Buffered channels seem to reduce blocking 
but I feel they come with the cost of such side effects like my initial 
problem of forgotten results in their channels. 


that happens with unbuffered channel too, if, for example, you mix it with 
a select on context cancellation.
Maybe you are lucky and your data source provides a acknowledgment 
mechanism, maybe you are not and it s up to you to work around.
This becomes a problem when the code can t be rationalized via an api that 
is able to wrap those behaviors.

On Tuesday, December 18, 2018 at 8:50:20 PM UTC+1, Chris Burkert wrote:
>
> Robert,
> it seems to me that you have a clear understanding about unbuffered vs. 
> buffered channels. I feel unbuffered channels are safer to use especially 
> in an acyclic directed graph of flowing values. Buffered channels seem to 
> reduce blocking but I feel they come with the cost of such side effects 
> like my initial problem of forgotten results in their channels. I would 
> love to hear/read/see more on the unbuffered vs. buffered tradeoff to get 
> rid of this gut feeling I am currently based on :-). Any good article you 
> can point me to?
> Thanks
>
> Robert Engels > schrieb am Di. 18. 
> Dez. 2018 um 17:03:
>
>> That code is incorrect as well when using buffered channels. 
>>
>> On Dec 18, 2018, at 10:00 AM, Skip Tavakkolian > > wrote:
>>
>> why not just  drop the select? i think the following is guaranteed 
>> because putting things on rc has to succeed before putting true into dc:
>>
>> package main
>>
>> import (
>> "fmt"
>> )
>>
>> func do(i int, rc chan<- int, dc chan<- bool) {
>> rc <- i
>> dc <- true
>> }
>>
>> func main() {
>> worker := 10
>> rc := make(chan int, worker)
>> done := 0
>> dc := make(chan bool, worker)
>> for i := 0; i < worker; i++ {
>> go do(i, rc, dc)
>> }
>> for done < worker {
>> r := <-rc
>> fmt.Println(r)
>> <-dc
>> done++
>> }
>> }
>>
>>
>> On Tue, Dec 18, 2018 at 5:35 AM Chris Burkert > > wrote:
>>
>>> Dear all,
>>>
>>> I have a couple of goroutines sending multiple results over a channel - 
>>> a simple fan-in. They signal the completion on a done channel. Main selects 
>>> on the results and done channel in parallel. As the select is random main 
>>> sometimes misses to select the last result. What would be the idiomatic way 
>>> to prevent this and completely drain the result channel?
>>>
>>> Here is a minmal example which sometimes prints one 0 but should always 
>>> print two of them:
>>>
>>> package main
>>>
>>> import (
>>> "fmt"
>>> )
>>>
>>> func do(rc chan<- int, dc chan<- bool) {
>>> rc <- 0
>>> dc <- true
>>> }
>>>
>>> func main() {
>>> worker := 2
>>> rc := make(chan int, worker)
>>> done := 0
>>> dc := make(chan bool, worker)
>>> for i := 0; i < worker; i++ {
>>> go do(rc, dc)
>>> }
>>> for done < worker {
>>> select {
>>> case <-dc:
>>> done++
>>> case r := <-rc:
>>> fmt.Println(r)
>>> }
>>> }
>>> }
>>>
>>> many thanks
>>> Chris
>>>
>>> -- 
>>> 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...@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...@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.


Re: [go-nuts] Channels: selecting the last element

2018-12-18 Thread robert engels
This may be a helpful read:

https://dave.cheney.net/2013/04/30/curious-channels

> On Dec 18, 2018, at 2:02 PM, robert engels  wrote:
> 
> To clarify the semantics aspects:
> 
> If A cannot proceed until B performs it’s work, because there is a 
> dependency, then using a unbuffered channel simplifies a lot - you will 
> always be at most “one event ahead” without any extra synchronization (wait 
> groups, etc.)
> 
>> On Dec 18, 2018, at 2:01 PM, robert engels > > wrote:
>> 
>> Whether to use buffered or unbuffered comes down to two things:
>> 
>> 1) the semantics of the communication. because using unbuffered channels 
>> simplifies a lot - knowing the send will not complete until the read 
>> completes - it provides a synchronization mechanism between events/messages 
>> and routines.
>> 
>> 2) performance… imagine the following pseudo code:
>> 
>> routine A sends messages to routine B
>> routine B's processing of messages is variable - sometimes very fast, 
>> sometimes very slow…
>> --- for example, let B be a logger, that every once in a while needs to 
>> write to disk (the much slower operation)
>> 
>> so if A is a low latency event processor - getting stuck trying to send to B 
>> would not be ideal - but since this only happens ‘rarely’ by using a 
>> buffered channel (with the size = number of events expected in a B “slow” 
>> time), you avoid “blocking” A
>> 
>> for example, A is sending financial orders to an exchange - you would not 
>> want to every slow A down just because the logger was slow
>> 
>> For the performance aspect, you are essentially increasing the parallelism, 
>> since any “block/wait” degrades this
>> 
>> Hope that helps.
>> 
>> 
>> 
>>> On Dec 18, 2018, at 1:49 PM, Chris Burkert >> > wrote:
>>> 
>>> Robert,
>>> it seems to me that you have a clear understanding about unbuffered vs. 
>>> buffered channels. I feel unbuffered channels are safer to use especially 
>>> in an acyclic directed graph of flowing values. Buffered channels seem to 
>>> reduce blocking but I feel they come with the cost of such side effects 
>>> like my initial problem of forgotten results in their channels. I would 
>>> love to hear/read/see more on the unbuffered vs. buffered tradeoff to get 
>>> rid of this gut feeling I am currently based on :-). Any good article you 
>>> can point me to?
>>> Thanks
>>> 
>>> Robert Engels mailto:reng...@ix.netcom.com>> 
>>> schrieb am Di. 18. Dez. 2018 um 17:03:
>>> That code is incorrect as well when using buffered channels. 
>>> 
>>> On Dec 18, 2018, at 10:00 AM, Skip Tavakkolian >> > wrote:
>>> 
 why not just  drop the select? i think the following is guaranteed because 
 putting things on rc has to succeed before putting true into dc:
 
 package main
 
 import (
"fmt"
 )
 
 func do(i int, rc chan<- int, dc chan<- bool) {
rc <- i
dc <- true
 }
 
 func main() {
worker := 10
rc := make(chan int, worker)
done := 0
dc := make(chan bool, worker)
for i := 0; i < worker; i++ {
go do(i, rc, dc)
}
for done < worker {
r := <-rc
fmt.Println(r)
<-dc
done++
}
 }
 
 
 On Tue, Dec 18, 2018 at 5:35 AM Chris Burkert >>> > wrote:
 Dear all,
 
 I have a couple of goroutines sending multiple results over a channel - a 
 simple fan-in. They signal the completion on a done channel. Main selects 
 on the results and done channel in parallel. As the select is random main 
 sometimes misses to select the last result. What would be the idiomatic 
 way to prevent this and completely drain the result channel?
 
 Here is a minmal example which sometimes prints one 0 but should always 
 print two of them:
 
 package main
 
 import (
 "fmt"
 )
 
 func do(rc chan<- int, dc chan<- bool) {
 rc <- 0
 dc <- true
 }
 
 func main() {
 worker := 2
 rc := make(chan int, worker)
 done := 0
 dc := make(chan bool, worker)
 for i := 0; i < worker; i++ {
 go do(rc, dc)
 }
 for done < worker {
 select {
 case <-dc:
 done++
 case r := <-rc:
 fmt.Println(r)
 }
 }
 }
 
 many thanks
 Chris
 
 -- 
 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 
 

Re: [go-nuts] Channels: selecting the last element

2018-12-18 Thread robert engels
To clarify the semantics aspects:

If A cannot proceed until B performs it’s work, because there is a dependency, 
then using a unbuffered channel simplifies a lot - you will always be at most 
“one event ahead” without any extra synchronization (wait groups, etc.)

> On Dec 18, 2018, at 2:01 PM, robert engels  wrote:
> 
> Whether to use buffered or unbuffered comes down to two things:
> 
> 1) the semantics of the communication. because using unbuffered channels 
> simplifies a lot - knowing the send will not complete until the read 
> completes - it provides a synchronization mechanism between events/messages 
> and routines.
> 
> 2) performance… imagine the following pseudo code:
> 
> routine A sends messages to routine B
> routine B's processing of messages is variable - sometimes very fast, 
> sometimes very slow…
> --- for example, let B be a logger, that every once in a while needs to 
> write to disk (the much slower operation)
> 
> so if A is a low latency event processor - getting stuck trying to send to B 
> would not be ideal - but since this only happens ‘rarely’ by using a buffered 
> channel (with the size = number of events expected in a B “slow” time), you 
> avoid “blocking” A
> 
> for example, A is sending financial orders to an exchange - you would not 
> want to every slow A down just because the logger was slow
> 
> For the performance aspect, you are essentially increasing the parallelism, 
> since any “block/wait” degrades this
> 
> Hope that helps.
> 
> 
> 
>> On Dec 18, 2018, at 1:49 PM, Chris Burkert > > wrote:
>> 
>> Robert,
>> it seems to me that you have a clear understanding about unbuffered vs. 
>> buffered channels. I feel unbuffered channels are safer to use especially in 
>> an acyclic directed graph of flowing values. Buffered channels seem to 
>> reduce blocking but I feel they come with the cost of such side effects like 
>> my initial problem of forgotten results in their channels. I would love to 
>> hear/read/see more on the unbuffered vs. buffered tradeoff to get rid of 
>> this gut feeling I am currently based on :-). Any good article you can point 
>> me to?
>> Thanks
>> 
>> Robert Engels mailto:reng...@ix.netcom.com>> schrieb 
>> am Di. 18. Dez. 2018 um 17:03:
>> That code is incorrect as well when using buffered channels. 
>> 
>> On Dec 18, 2018, at 10:00 AM, Skip Tavakkolian > > wrote:
>> 
>>> why not just  drop the select? i think the following is guaranteed because 
>>> putting things on rc has to succeed before putting true into dc:
>>> 
>>> package main
>>> 
>>> import (
>>> "fmt"
>>> )
>>> 
>>> func do(i int, rc chan<- int, dc chan<- bool) {
>>> rc <- i
>>> dc <- true
>>> }
>>> 
>>> func main() {
>>> worker := 10
>>> rc := make(chan int, worker)
>>> done := 0
>>> dc := make(chan bool, worker)
>>> for i := 0; i < worker; i++ {
>>> go do(i, rc, dc)
>>> }
>>> for done < worker {
>>> r := <-rc
>>> fmt.Println(r)
>>> <-dc
>>> done++
>>> }
>>> }
>>> 
>>> 
>>> On Tue, Dec 18, 2018 at 5:35 AM Chris Burkert >> > wrote:
>>> Dear all,
>>> 
>>> I have a couple of goroutines sending multiple results over a channel - a 
>>> simple fan-in. They signal the completion on a done channel. Main selects 
>>> on the results and done channel in parallel. As the select is random main 
>>> sometimes misses to select the last result. What would be the idiomatic way 
>>> to prevent this and completely drain the result channel?
>>> 
>>> Here is a minmal example which sometimes prints one 0 but should always 
>>> print two of them:
>>> 
>>> package main
>>> 
>>> import (
>>> "fmt"
>>> )
>>> 
>>> func do(rc chan<- int, dc chan<- bool) {
>>> rc <- 0
>>> dc <- true
>>> }
>>> 
>>> func main() {
>>> worker := 2
>>> rc := make(chan int, worker)
>>> done := 0
>>> dc := make(chan bool, worker)
>>> for i := 0; i < worker; i++ {
>>> go do(rc, dc)
>>> }
>>> for done < worker {
>>> select {
>>> case <-dc:
>>> done++
>>> case r := <-rc:
>>> fmt.Println(r)
>>> }
>>> }
>>> }
>>> 
>>> many thanks
>>> Chris
>>> 
>>> -- 
>>> 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 

Re: [go-nuts] Channels: selecting the last element

2018-12-18 Thread robert engels
Whether to use buffered or unbuffered comes down to two things:

1) the semantics of the communication. because using unbuffered channels 
simplifies a lot - knowing the send will not complete until the read completes 
- it provides a synchronization mechanism between events/messages and routines.

2) performance… imagine the following pseudo code:

routine A sends messages to routine B
routine B's processing of messages is variable - sometimes very fast, sometimes 
very slow…
--- for example, let B be a logger, that every once in a while needs to 
write to disk (the much slower operation)

so if A is a low latency event processor - getting stuck trying to send to B 
would not be ideal - but since this only happens ‘rarely’ by using a buffered 
channel (with the size = number of events expected in a B “slow” time), you 
avoid “blocking” A

for example, A is sending financial orders to an exchange - you would not want 
to every slow A down just because the logger was slow

For the performance aspect, you are essentially increasing the parallelism, 
since any “block/wait” degrades this

Hope that helps.



> On Dec 18, 2018, at 1:49 PM, Chris Burkert  wrote:
> 
> Robert,
> it seems to me that you have a clear understanding about unbuffered vs. 
> buffered channels. I feel unbuffered channels are safer to use especially in 
> an acyclic directed graph of flowing values. Buffered channels seem to reduce 
> blocking but I feel they come with the cost of such side effects like my 
> initial problem of forgotten results in their channels. I would love to 
> hear/read/see more on the unbuffered vs. buffered tradeoff to get rid of this 
> gut feeling I am currently based on :-). Any good article you can point me to?
> Thanks
> 
> Robert Engels mailto:reng...@ix.netcom.com>> schrieb 
> am Di. 18. Dez. 2018 um 17:03:
> That code is incorrect as well when using buffered channels. 
> 
> On Dec 18, 2018, at 10:00 AM, Skip Tavakkolian  > wrote:
> 
>> why not just  drop the select? i think the following is guaranteed because 
>> putting things on rc has to succeed before putting true into dc:
>> 
>> package main
>> 
>> import (
>>  "fmt"
>> )
>> 
>> func do(i int, rc chan<- int, dc chan<- bool) {
>>  rc <- i
>>  dc <- true
>> }
>> 
>> func main() {
>>  worker := 10
>>  rc := make(chan int, worker)
>>  done := 0
>>  dc := make(chan bool, worker)
>>  for i := 0; i < worker; i++ {
>>  go do(i, rc, dc)
>>  }
>>  for done < worker {
>>  r := <-rc
>>  fmt.Println(r)
>>  <-dc
>>  done++
>>  }
>> }
>> 
>> 
>> On Tue, Dec 18, 2018 at 5:35 AM Chris Burkert > > wrote:
>> Dear all,
>> 
>> I have a couple of goroutines sending multiple results over a channel - a 
>> simple fan-in. They signal the completion on a done channel. Main selects on 
>> the results and done channel in parallel. As the select is random main 
>> sometimes misses to select the last result. What would be the idiomatic way 
>> to prevent this and completely drain the result channel?
>> 
>> Here is a minmal example which sometimes prints one 0 but should always 
>> print two of them:
>> 
>> package main
>> 
>> import (
>> "fmt"
>> )
>> 
>> func do(rc chan<- int, dc chan<- bool) {
>> rc <- 0
>> dc <- true
>> }
>> 
>> func main() {
>> worker := 2
>> rc := make(chan int, worker)
>> done := 0
>> dc := make(chan bool, worker)
>> for i := 0; i < worker; i++ {
>> go do(rc, dc)
>> }
>> for done < worker {
>> select {
>> case <-dc:
>> done++
>> case r := <-rc:
>> fmt.Println(r)
>> }
>> }
>> }
>> 
>> many thanks
>> Chris
>> 
>> -- 
>> 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 
>> .

-- 
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 

Re: [go-nuts] Channels: selecting the last element

2018-12-18 Thread robert engels
What he is saying is that a closed channel is always ready to be received, so 
in your code, you could achieve closed++ twice on the same channel...

> On Dec 18, 2018, at 1:38 PM, Chris Burkert  wrote:
> 
> Justin,
> I don‘t understand that. Maybe I am wrong but I think this is not an issue 
> anymore with the wait group as Ian proposed. It fully replaces the done 
> channel by closing all result channels while the select keeps on reading from 
> the result channels until they are all closed and empty. Please correct me if 
> I am wrong.
> Chris
> 
> Justin Israel mailto:justinisr...@gmail.com>> 
> schrieb am Di. 18. Dez. 2018 um 19:08:
> 
> 
> On Wed, Dec 19, 2018, 5:31 AM Chris Burkert  > wrote:
> Hello Ian, all,
> yes, the workers generate multiple results. I was able to use your proposal 
> with the waiting goroutine which closes the channel. Unfortunately my initial 
> minimal example was not so minimal. It is a little more complicated, as I 
> have multiple "result" channels with different types and I don't know how 
> many values I get. So I can't just range over one channel but instead use 
> select with the ok from "val, ok := <-channel" to count the closed channels 
> which finally ends the loop. Below is what I came up with (using Johns 
> approach to run it multiple times) and it seems to be deterministic.
> Many thanks!
> PS: with buffered channels I have to disable closed channels with "channel = 
> nil" to make it work.
> 
> You should need to disable the closed channel by setting it nil regardless of 
> it being buffered or not. Depending on how you actually end up sending 
> results back on multiple channels it could still be a bug if you end up 
> selecting on the closed channel multiple times and think you are done instead 
> of reading from another channel with results. 
> 
> 
> package main
> 
> import (
> "fmt"
> "sync"
> )
> 
> func do(fc chan<- int, rc chan<- string) {
> fc <- 42
> fc <- 43
> rc <- "foo"
> }
> 
> func main() {
> w := 4
> r := 10
> n := 0
> for i := 0; i < r; i++ {
> n = n + run(w)
> }
> fmt.Printf("Got %d, expected %d\n", n, 3*w*r)
> }
> 
> func run(worker int) int {
> fc := make(chan int)
> rc := make(chan string)
> var wg sync.WaitGroup
> wg.Add(worker)
> for i := 0; i < worker; i++ {
> go func() {
> defer wg.Done()
> do(fc, rc)
> }()
> }
> go func() {
> wg.Wait()
> close(fc)
> close(rc)
> }()
> n := 0
> closed := 0
> for closed < 2 {
> select {
> case _, ok := <-fc:
> if ok {
> n++
> } else {
> closed++
> }
> case _, ok := <-rc:
> if ok {
> n++
> } else {
> closed++
> }
> }
> }
> return n
> }
> 
> Am Di., 18. Dez. 2018 um 15:50 Uhr schrieb Ian Lance Taylor  >:
> On Tue, Dec 18, 2018 at 5:35 AM Chris Burkert  > wrote:
> >
> > I have a couple of goroutines sending multiple results over a channel - a 
> > simple fan-in. They signal the completion on a done channel. Main selects 
> > on the results and done channel in parallel. As the select is random main 
> > sometimes misses to select the last result. What would be the idiomatic way 
> > to prevent this and completely drain the result channel?
> >
> > Here is a minmal example which sometimes prints one 0 but should always 
> > print two of them:
> >
> > package main
> >
> > import (
> > "fmt"
> > )
> >
> > func do(rc chan<- int, dc chan<- bool) {
> > rc <- 0
> > dc <- true
> > }
> >
> > func main() {
> > worker := 2
> > rc := make(chan int, worker)
> > done := 0
> > dc := make(chan bool, worker)
> > for i := 0; i < worker; i++ {
> > go do(rc, dc)
> > }
> > for done < worker {
> > select {
> > case <-dc:
> > done++
> > case r := <-rc:
> > fmt.Println(r)
> > }
> > }
> > }
> 
> 
> I assume the workers can generate multiple results, as otherwise the
> done marker seems pointless.  In general the simplest way to signal
> completion on a channel is to call close.  The simplest way to call
> close on a fan-in is to have another goroutine that waits for the
> other goroutines and closes the channel.  That might look like
> 
> package main
> 
> import (
>  

Re: [go-nuts] Channels: selecting the last element

2018-12-18 Thread Chris Burkert
Robert,
it seems to me that you have a clear understanding about unbuffered vs.
buffered channels. I feel unbuffered channels are safer to use especially
in an acyclic directed graph of flowing values. Buffered channels seem to
reduce blocking but I feel they come with the cost of such side effects
like my initial problem of forgotten results in their channels. I would
love to hear/read/see more on the unbuffered vs. buffered tradeoff to get
rid of this gut feeling I am currently based on :-). Any good article you
can point me to?
Thanks

Robert Engels  schrieb am Di. 18. Dez. 2018 um 17:03:

> That code is incorrect as well when using buffered channels.
>
> On Dec 18, 2018, at 10:00 AM, Skip Tavakkolian 
> wrote:
>
> why not just  drop the select? i think the following is guaranteed because
> putting things on rc has to succeed before putting true into dc:
>
> package main
>
> import (
> "fmt"
> )
>
> func do(i int, rc chan<- int, dc chan<- bool) {
> rc <- i
> dc <- true
> }
>
> func main() {
> worker := 10
> rc := make(chan int, worker)
> done := 0
> dc := make(chan bool, worker)
> for i := 0; i < worker; i++ {
> go do(i, rc, dc)
> }
> for done < worker {
> r := <-rc
> fmt.Println(r)
> <-dc
> done++
> }
> }
>
>
> On Tue, Dec 18, 2018 at 5:35 AM Chris Burkert 
> wrote:
>
>> Dear all,
>>
>> I have a couple of goroutines sending multiple results over a channel - a
>> simple fan-in. They signal the completion on a done channel. Main selects
>> on the results and done channel in parallel. As the select is random main
>> sometimes misses to select the last result. What would be the idiomatic way
>> to prevent this and completely drain the result channel?
>>
>> Here is a minmal example which sometimes prints one 0 but should always
>> print two of them:
>>
>> package main
>>
>> import (
>> "fmt"
>> )
>>
>> func do(rc chan<- int, dc chan<- bool) {
>> rc <- 0
>> dc <- true
>> }
>>
>> func main() {
>> worker := 2
>> rc := make(chan int, worker)
>> done := 0
>> dc := make(chan bool, worker)
>> for i := 0; i < worker; i++ {
>> go do(rc, dc)
>> }
>> for done < worker {
>> select {
>> case <-dc:
>> done++
>> case r := <-rc:
>> fmt.Println(r)
>> }
>> }
>> }
>>
>> many thanks
>> Chris
>>
>> --
>> 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.
>
>

-- 
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] Channels: selecting the last element

2018-12-18 Thread Chris Burkert
Justin,
I don‘t understand that. Maybe I am wrong but I think this is not an issue
anymore with the wait group as Ian proposed. It fully replaces the done
channel by closing all result channels while the select keeps on reading
from the result channels until they are all closed and empty. Please
correct me if I am wrong.
Chris

Justin Israel  schrieb am Di. 18. Dez. 2018 um
19:08:

>
>
> On Wed, Dec 19, 2018, 5:31 AM Chris Burkert 
> wrote:
>
>> Hello Ian, all,
>> yes, the workers generate multiple results. I was able to use your
>> proposal with the waiting goroutine which closes the channel. Unfortunately
>> my initial minimal example was not so minimal. It is a little more
>> complicated, as I have multiple "result" channels with different types and
>> I don't know how many values I get. So I can't just range over one channel
>> but instead use select with the ok from "val, ok := <-channel" to count the
>> closed channels which finally ends the loop. Below is what I came up with
>> (using Johns approach to run it multiple times) and it seems to be
>> deterministic.
>> Many thanks!
>> PS: with buffered channels I have to disable closed channels with
>> "channel = nil" to make it work.
>>
>
> You should need to disable the closed channel by setting it nil regardless
> of it being buffered or not. Depending on how you actually end up sending
> results back on multiple channels it could still be a bug if you end up
> selecting on the closed channel multiple times and think you are done
> instead of reading from another channel with results.
>
>
>> package main
>>
>> import (
>> "fmt"
>> "sync"
>> )
>>
>> func do(fc chan<- int, rc chan<- string) {
>> fc <- 42
>> fc <- 43
>> rc <- "foo"
>> }
>>
>> func main() {
>> w := 4
>> r := 10
>> n := 0
>> for i := 0; i < r; i++ {
>> n = n + run(w)
>> }
>> fmt.Printf("Got %d, expected %d\n", n, 3*w*r)
>> }
>>
>> func run(worker int) int {
>> fc := make(chan int)
>> rc := make(chan string)
>> var wg sync.WaitGroup
>> wg.Add(worker)
>> for i := 0; i < worker; i++ {
>> go func() {
>> defer wg.Done()
>> do(fc, rc)
>> }()
>> }
>> go func() {
>> wg.Wait()
>> close(fc)
>> close(rc)
>> }()
>> n := 0
>> closed := 0
>> for closed < 2 {
>> select {
>> case _, ok := <-fc:
>> if ok {
>> n++
>> } else {
>> closed++
>> }
>> case _, ok := <-rc:
>> if ok {
>> n++
>> } else {
>> closed++
>> }
>> }
>> }
>> return n
>> }
>>
>> Am Di., 18. Dez. 2018 um 15:50 Uhr schrieb Ian Lance Taylor <
>> i...@golang.org>:
>>
>>> On Tue, Dec 18, 2018 at 5:35 AM Chris Burkert 
>>> wrote:
>>> >
>>> > I have a couple of goroutines sending multiple results over a channel
>>> - a simple fan-in. They signal the completion on a done channel. Main
>>> selects on the results and done channel in parallel. As the select is
>>> random main sometimes misses to select the last result. What would be the
>>> idiomatic way to prevent this and completely drain the result channel?
>>> >
>>> > Here is a minmal example which sometimes prints one 0 but should
>>> always print two of them:
>>> >
>>> > package main
>>> >
>>> > import (
>>> > "fmt"
>>> > )
>>> >
>>> > func do(rc chan<- int, dc chan<- bool) {
>>> > rc <- 0
>>> > dc <- true
>>> > }
>>> >
>>> > func main() {
>>> > worker := 2
>>> > rc := make(chan int, worker)
>>> > done := 0
>>> > dc := make(chan bool, worker)
>>> > for i := 0; i < worker; i++ {
>>> > go do(rc, dc)
>>> > }
>>> > for done < worker {
>>> > select {
>>> > case <-dc:
>>> > done++
>>> > case r := <-rc:
>>> > fmt.Println(r)
>>> > }
>>> > }
>>> > }
>>>
>>>
>>> I assume the workers can generate multiple results, as otherwise the
>>> done marker seems pointless.  In general the simplest way to signal
>>> completion on a channel is to call close.  The simplest way to call
>>> close on a fan-in is to have another goroutine that waits for the
>>> other goroutines and closes the channel.  That might look like
>>>
>>> package main
>>>
>>> import (
>>> "fmt"
>>> "sync"
>>> )
>>>
>>> func do(rc chan<- int) {
>>> rc <- 0
>>> }
>>>
>>> func main() {
>>> worker := 2
>>> rc := make(chan int, worker)
>>> 

Re: [go-nuts] Channels: selecting the last element

2018-12-18 Thread Diane Looney
Just realized what you meant about buffered channels. I'm wrong, and sorry
for the confusion.

+1 to your original solution (combined with setting channels to nil).

Diane Looney


On Tue, Dec 18, 2018 at 11:31 AM Chris Burkert 
wrote:

> Hello Ian, all,
> yes, the workers generate multiple results. I was able to use your
> proposal with the waiting goroutine which closes the channel. Unfortunately
> my initial minimal example was not so minimal. It is a little more
> complicated, as I have multiple "result" channels with different types and
> I don't know how many values I get. So I can't just range over one channel
> but instead use select with the ok from "val, ok := <-channel" to count the
> closed channels which finally ends the loop. Below is what I came up with
> (using Johns approach to run it multiple times) and it seems to be
> deterministic.
> Many thanks!
> PS: with buffered channels I have to disable closed channels with "channel
> = nil" to make it work.
>
> package main
>
> import (
> "fmt"
> "sync"
> )
>
> func do(fc chan<- int, rc chan<- string) {
> fc <- 42
> fc <- 43
> rc <- "foo"
> }
>
> func main() {
> w := 4
> r := 10
> n := 0
> for i := 0; i < r; i++ {
> n = n + run(w)
> }
> fmt.Printf("Got %d, expected %d\n", n, 3*w*r)
> }
>
> func run(worker int) int {
> fc := make(chan int)
> rc := make(chan string)
> var wg sync.WaitGroup
> wg.Add(worker)
> for i := 0; i < worker; i++ {
> go func() {
> defer wg.Done()
> do(fc, rc)
> }()
> }
> go func() {
> wg.Wait()
> close(fc)
> close(rc)
> }()
> n := 0
> closed := 0
> for closed < 2 {
> select {
> case _, ok := <-fc:
> if ok {
> n++
> } else {
> closed++
> }
> case _, ok := <-rc:
> if ok {
> n++
> } else {
> closed++
> }
> }
> }
> return n
> }
>
> Am Di., 18. Dez. 2018 um 15:50 Uhr schrieb Ian Lance Taylor <
> i...@golang.org>:
>
>> On Tue, Dec 18, 2018 at 5:35 AM Chris Burkert 
>> wrote:
>> >
>> > I have a couple of goroutines sending multiple results over a channel -
>> a simple fan-in. They signal the completion on a done channel. Main selects
>> on the results and done channel in parallel. As the select is random main
>> sometimes misses to select the last result. What would be the idiomatic way
>> to prevent this and completely drain the result channel?
>> >
>> > Here is a minmal example which sometimes prints one 0 but should always
>> print two of them:
>> >
>> > package main
>> >
>> > import (
>> > "fmt"
>> > )
>> >
>> > func do(rc chan<- int, dc chan<- bool) {
>> > rc <- 0
>> > dc <- true
>> > }
>> >
>> > func main() {
>> > worker := 2
>> > rc := make(chan int, worker)
>> > done := 0
>> > dc := make(chan bool, worker)
>> > for i := 0; i < worker; i++ {
>> > go do(rc, dc)
>> > }
>> > for done < worker {
>> > select {
>> > case <-dc:
>> > done++
>> > case r := <-rc:
>> > fmt.Println(r)
>> > }
>> > }
>> > }
>>
>>
>> I assume the workers can generate multiple results, as otherwise the
>> done marker seems pointless.  In general the simplest way to signal
>> completion on a channel is to call close.  The simplest way to call
>> close on a fan-in is to have another goroutine that waits for the
>> other goroutines and closes the channel.  That might look like
>>
>> package main
>>
>> import (
>> "fmt"
>> "sync"
>> )
>>
>> func do(rc chan<- int) {
>> rc <- 0
>> }
>>
>> func main() {
>> worker := 2
>> rc := make(chan int, worker)
>> var wg sync.WaitGroup
>> wg.Add(worker)
>> for i := 0; i < worker; i++ {
>> go func() {
>> defer wg.Done()
>> do(rc)
>> }()
>> }
>> go func() {
>> wg.Wait()
>> close(rc)
>> }()
>> for r := range rc {
>> fmt.Println(r)
>> }
>> }
>>
>> Ian
>>
> --
> 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 

Re: [go-nuts] Channels: selecting the last element

2018-12-18 Thread Diane Looney
I'm not sure this code behaves as you expect it to. I don't think there's
any magic in place to prevent select from picking the same closed channel
more than once. For example:

https://play.golang.org/p/nVvsBxww_Rb

package main

import (
"fmt"
"sync"
)

func test() {
c1 := make(chan bool, 1000)
c2 := make(chan bool)
closed := 0
closedByC1 := 0
closedByC2 := 0
n := 0
for i := 0; i < 1000; i++ {
c1 <- true
}
close(c1)
close(c2)
for closed < 2 {
select {
case _, ok := <-c1:
if !ok {
closed++
closedByC1++
} else {
n++
}
case _, ok := <-c2:
if !ok {
closed++
closedByC2++
} else {
n++
}
}
}
fmt.Printf("%v\t%v\t%v\t%v\n", n, closed, closedByC1, closedByC2)
}
func main() {
wg := sync.WaitGroup{}
wg.Add(20)
for i := 0; i < 20; i++ {
go func() {
defer wg.Done()
test()
}()
}
wg.Wait()
}


I think if you want to do this, you should instead go down the route of
multiple goroutines that all signal on a waitgroup for each job type.

https://play.golang.org/p/DG9Aes_rqoR

package main

import (
"fmt"
"sync"
)

func do(fc chan<- int, rc chan<- string) {
fc <- 42
fc <- 43
rc <- "foo"
}

func main() {
w := 4
r := 10
n := 0
for i := 0; i < r; i++ {
n = n + run(w)
}
fmt.Printf("Got %d, expected %d\n", n, 3*w*r)
}

func run(worker int) int {
fc := make(chan int, 10)
rc := make(chan string)
wg1 := sync.WaitGroup{}
wg1.Add(worker)
for i := 0; i < worker; i++ {
go func () {
defer wg1.Done()
do(fc, rc)
}()
}

wg2 := sync.WaitGroup{}
wg2.Add(2)

n:=0
go func() {
defer wg2.Done()
for {
_, ok := <- fc
if ! ok {
return
}
n++
}
}()
go func() {
defer wg2.Done()
for {
_, ok := <- rc
if ! ok {
return
}
n++
}
}()

wg1.Wait()
close(fc)
close(rc)
wg2.Wait()

return n
}

Diane Looney


On Tue, Dec 18, 2018 at 11:31 AM Chris Burkert 
wrote:

> Hello Ian, all,
> yes, the workers generate multiple results. I was able to use your
> proposal with the waiting goroutine which closes the channel. Unfortunately
> my initial minimal example was not so minimal. It is a little more
> complicated, as I have multiple "result" channels with different types and
> I don't know how many values I get. So I can't just range over one channel
> but instead use select with the ok from "val, ok := <-channel" to count the
> closed channels which finally ends the loop. Below is what I came up with
> (using Johns approach to run it multiple times) and it seems to be
> deterministic.
> Many thanks!
> PS: with buffered channels I have to disable closed channels with "channel
> = nil" to make it work.
>
> package main
>
> import (
> "fmt"
> "sync"
> )
>
> func do(fc chan<- int, rc chan<- string) {
> fc <- 42
> fc <- 43
> rc <- "foo"
> }
>
> func main() {
> w := 4
> r := 10
> n := 0
> for i := 0; i < r; i++ {
> n = n + run(w)
> }
> fmt.Printf("Got %d, expected %d\n", n, 3*w*r)
> }
>
> func run(worker int) int {
> fc := make(chan int)
> rc := make(chan string)
> var wg sync.WaitGroup
> wg.Add(worker)
> for i := 0; i < worker; i++ {
> go func() {
> defer wg.Done()
> do(fc, rc)
> }()
> }
> go func() {
> wg.Wait()
> close(fc)
> close(rc)
> }()
> n := 0
> closed := 0
> for closed < 2 {
> select {
> case _, ok := <-fc:
> if ok {
> n++
> } else {
> closed++
> }
> case _, ok := <-rc:
> if ok {
> n++
> } else {
> closed++
> }
> }
> }
> return n
> }
>
> Am Di., 18. Dez. 2018 um 15:50 Uhr schrieb Ian Lance Taylor <
> i...@golang.org>:
>
>> On Tue, Dec 18, 2018 at 5:35 AM Chris Burkert 
>> wrote:
>> >
>> > I have a couple of goroutines sending multiple results over a channel -
>> a simple fan-in. 

Re: [go-nuts] Channels: selecting the last element

2018-12-18 Thread Justin Israel
On Wed, Dec 19, 2018, 5:31 AM Chris Burkert  wrote:

> Hello Ian, all,
> yes, the workers generate multiple results. I was able to use your
> proposal with the waiting goroutine which closes the channel. Unfortunately
> my initial minimal example was not so minimal. It is a little more
> complicated, as I have multiple "result" channels with different types and
> I don't know how many values I get. So I can't just range over one channel
> but instead use select with the ok from "val, ok := <-channel" to count the
> closed channels which finally ends the loop. Below is what I came up with
> (using Johns approach to run it multiple times) and it seems to be
> deterministic.
> Many thanks!
> PS: with buffered channels I have to disable closed channels with "channel
> = nil" to make it work.
>

You should need to disable the closed channel by setting it nil regardless
of it being buffered or not. Depending on how you actually end up sending
results back on multiple channels it could still be a bug if you end up
selecting on the closed channel multiple times and think you are done
instead of reading from another channel with results.


> package main
>
> import (
> "fmt"
> "sync"
> )
>
> func do(fc chan<- int, rc chan<- string) {
> fc <- 42
> fc <- 43
> rc <- "foo"
> }
>
> func main() {
> w := 4
> r := 10
> n := 0
> for i := 0; i < r; i++ {
> n = n + run(w)
> }
> fmt.Printf("Got %d, expected %d\n", n, 3*w*r)
> }
>
> func run(worker int) int {
> fc := make(chan int)
> rc := make(chan string)
> var wg sync.WaitGroup
> wg.Add(worker)
> for i := 0; i < worker; i++ {
> go func() {
> defer wg.Done()
> do(fc, rc)
> }()
> }
> go func() {
> wg.Wait()
> close(fc)
> close(rc)
> }()
> n := 0
> closed := 0
> for closed < 2 {
> select {
> case _, ok := <-fc:
> if ok {
> n++
> } else {
> closed++
> }
> case _, ok := <-rc:
> if ok {
> n++
> } else {
> closed++
> }
> }
> }
> return n
> }
>
> Am Di., 18. Dez. 2018 um 15:50 Uhr schrieb Ian Lance Taylor <
> i...@golang.org>:
>
>> On Tue, Dec 18, 2018 at 5:35 AM Chris Burkert 
>> wrote:
>> >
>> > I have a couple of goroutines sending multiple results over a channel -
>> a simple fan-in. They signal the completion on a done channel. Main selects
>> on the results and done channel in parallel. As the select is random main
>> sometimes misses to select the last result. What would be the idiomatic way
>> to prevent this and completely drain the result channel?
>> >
>> > Here is a minmal example which sometimes prints one 0 but should always
>> print two of them:
>> >
>> > package main
>> >
>> > import (
>> > "fmt"
>> > )
>> >
>> > func do(rc chan<- int, dc chan<- bool) {
>> > rc <- 0
>> > dc <- true
>> > }
>> >
>> > func main() {
>> > worker := 2
>> > rc := make(chan int, worker)
>> > done := 0
>> > dc := make(chan bool, worker)
>> > for i := 0; i < worker; i++ {
>> > go do(rc, dc)
>> > }
>> > for done < worker {
>> > select {
>> > case <-dc:
>> > done++
>> > case r := <-rc:
>> > fmt.Println(r)
>> > }
>> > }
>> > }
>>
>>
>> I assume the workers can generate multiple results, as otherwise the
>> done marker seems pointless.  In general the simplest way to signal
>> completion on a channel is to call close.  The simplest way to call
>> close on a fan-in is to have another goroutine that waits for the
>> other goroutines and closes the channel.  That might look like
>>
>> package main
>>
>> import (
>> "fmt"
>> "sync"
>> )
>>
>> func do(rc chan<- int) {
>> rc <- 0
>> }
>>
>> func main() {
>> worker := 2
>> rc := make(chan int, worker)
>> var wg sync.WaitGroup
>> wg.Add(worker)
>> for i := 0; i < worker; i++ {
>> go func() {
>> defer wg.Done()
>> do(rc)
>> }()
>> }
>> go func() {
>> wg.Wait()
>> close(rc)
>> }()
>> for r := range rc {
>> fmt.Println(r)
>> }
>> }
>>
>> Ian
>>
> --
> You received this message because you are subscribed to the Google Groups
> "golang-nuts" group.
> To 

Re: [go-nuts] Channels: selecting the last element

2018-12-18 Thread Chris Burkert
Hello Ian, all,
yes, the workers generate multiple results. I was able to use your proposal
with the waiting goroutine which closes the channel. Unfortunately my
initial minimal example was not so minimal. It is a little more
complicated, as I have multiple "result" channels with different types and
I don't know how many values I get. So I can't just range over one channel
but instead use select with the ok from "val, ok := <-channel" to count the
closed channels which finally ends the loop. Below is what I came up with
(using Johns approach to run it multiple times) and it seems to be
deterministic.
Many thanks!
PS: with buffered channels I have to disable closed channels with "channel
= nil" to make it work.

package main

import (
"fmt"
"sync"
)

func do(fc chan<- int, rc chan<- string) {
fc <- 42
fc <- 43
rc <- "foo"
}

func main() {
w := 4
r := 10
n := 0
for i := 0; i < r; i++ {
n = n + run(w)
}
fmt.Printf("Got %d, expected %d\n", n, 3*w*r)
}

func run(worker int) int {
fc := make(chan int)
rc := make(chan string)
var wg sync.WaitGroup
wg.Add(worker)
for i := 0; i < worker; i++ {
go func() {
defer wg.Done()
do(fc, rc)
}()
}
go func() {
wg.Wait()
close(fc)
close(rc)
}()
n := 0
closed := 0
for closed < 2 {
select {
case _, ok := <-fc:
if ok {
n++
} else {
closed++
}
case _, ok := <-rc:
if ok {
n++
} else {
closed++
}
}
}
return n
}

Am Di., 18. Dez. 2018 um 15:50 Uhr schrieb Ian Lance Taylor :

> On Tue, Dec 18, 2018 at 5:35 AM Chris Burkert 
> wrote:
> >
> > I have a couple of goroutines sending multiple results over a channel -
> a simple fan-in. They signal the completion on a done channel. Main selects
> on the results and done channel in parallel. As the select is random main
> sometimes misses to select the last result. What would be the idiomatic way
> to prevent this and completely drain the result channel?
> >
> > Here is a minmal example which sometimes prints one 0 but should always
> print two of them:
> >
> > package main
> >
> > import (
> > "fmt"
> > )
> >
> > func do(rc chan<- int, dc chan<- bool) {
> > rc <- 0
> > dc <- true
> > }
> >
> > func main() {
> > worker := 2
> > rc := make(chan int, worker)
> > done := 0
> > dc := make(chan bool, worker)
> > for i := 0; i < worker; i++ {
> > go do(rc, dc)
> > }
> > for done < worker {
> > select {
> > case <-dc:
> > done++
> > case r := <-rc:
> > fmt.Println(r)
> > }
> > }
> > }
>
>
> I assume the workers can generate multiple results, as otherwise the
> done marker seems pointless.  In general the simplest way to signal
> completion on a channel is to call close.  The simplest way to call
> close on a fan-in is to have another goroutine that waits for the
> other goroutines and closes the channel.  That might look like
>
> package main
>
> import (
> "fmt"
> "sync"
> )
>
> func do(rc chan<- int) {
> rc <- 0
> }
>
> func main() {
> worker := 2
> rc := make(chan int, worker)
> var wg sync.WaitGroup
> wg.Add(worker)
> for i := 0; i < worker; i++ {
> go func() {
> defer wg.Done()
> do(rc)
> }()
> }
> go func() {
> wg.Wait()
> close(rc)
> }()
> for r := range rc {
> fmt.Println(r)
> }
> }
>
> Ian
>

-- 
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] Channels: selecting the last element

2018-12-18 Thread Burak Serdar
On Tue, Dec 18, 2018 at 9:01 AM Skip Tavakkolian
 wrote:
>
> why not just  drop the select? i think the following is guaranteed because 
> putting things on rc has to succeed before putting true into dc:

That will serialize all goroutines. They'll run one after the other.

>
> package main
>
> import (
> "fmt"
> )
>
> func do(i int, rc chan<- int, dc chan<- bool) {
> rc <- i
> dc <- true
> }
>
> func main() {
> worker := 10
> rc := make(chan int, worker)
> done := 0
> dc := make(chan bool, worker)
> for i := 0; i < worker; i++ {
> go do(i, rc, dc)
> }
> for done < worker {
> r := <-rc
> fmt.Println(r)
> <-dc
> done++
> }
> }
>
>
> On Tue, Dec 18, 2018 at 5:35 AM Chris Burkert  wrote:
>>
>> Dear all,
>>
>> I have a couple of goroutines sending multiple results over a channel - a 
>> simple fan-in. They signal the completion on a done channel. Main selects on 
>> the results and done channel in parallel. As the select is random main 
>> sometimes misses to select the last result. What would be the idiomatic way 
>> to prevent this and completely drain the result channel?
>>
>> Here is a minmal example which sometimes prints one 0 but should always 
>> print two of them:
>>
>> package main
>>
>> import (
>> "fmt"
>> )
>>
>> func do(rc chan<- int, dc chan<- bool) {
>> rc <- 0
>> dc <- true
>> }
>>
>> func main() {
>> worker := 2
>> rc := make(chan int, worker)
>> done := 0
>> dc := make(chan bool, worker)
>> for i := 0; i < worker; i++ {
>> go do(rc, dc)
>> }
>> for done < worker {
>> select {
>> case <-dc:
>> done++
>> case r := <-rc:
>> fmt.Println(r)
>> }
>> }
>> }
>>
>> many thanks
>> Chris
>>
>> --
>> 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.

-- 
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] Channels: selecting the last element

2018-12-18 Thread Robert Engels
Since there are multiple results needed to be processed ...

> On Dec 18, 2018, at 10:02 AM, Robert Engels  wrote:
> 
> That code is incorrect as well when using buffered channels. 
> 
>> On Dec 18, 2018, at 10:00 AM, Skip Tavakkolian  
>> wrote:
>> 
>> why not just  drop the select? i think the following is guaranteed because 
>> putting things on rc has to succeed before putting true into dc:
>> 
>> package main
>> 
>> import (
>>  "fmt"
>> )
>> 
>> func do(i int, rc chan<- int, dc chan<- bool) {
>>  rc <- i
>>  dc <- true
>> }
>> 
>> func main() {
>>  worker := 10
>>  rc := make(chan int, worker)
>>  done := 0
>>  dc := make(chan bool, worker)
>>  for i := 0; i < worker; i++ {
>>  go do(i, rc, dc)
>>  }
>>  for done < worker {
>>  r := <-rc
>>  fmt.Println(r)
>>  <-dc
>>  done++
>>  }
>> }
>> 
>> 
>>> On Tue, Dec 18, 2018 at 5:35 AM Chris Burkert  
>>> wrote:
>>> Dear all,
>>> 
>>> I have a couple of goroutines sending multiple results over a channel - a 
>>> simple fan-in. They signal the completion on a done channel. Main selects 
>>> on the results and done channel in parallel. As the select is random main 
>>> sometimes misses to select the last result. What would be the idiomatic way 
>>> to prevent this and completely drain the result channel?
>>> 
>>> Here is a minmal example which sometimes prints one 0 but should always 
>>> print two of them:
>>> 
>>> package main
>>> 
>>> import (
>>> "fmt"
>>> )
>>> 
>>> func do(rc chan<- int, dc chan<- bool) {
>>> rc <- 0
>>> dc <- true
>>> }
>>> 
>>> func main() {
>>> worker := 2
>>> rc := make(chan int, worker)
>>> done := 0
>>> dc := make(chan bool, worker)
>>> for i := 0; i < worker; i++ {
>>> go do(rc, dc)
>>> }
>>> for done < worker {
>>> select {
>>> case <-dc:
>>> done++
>>> case r := <-rc:
>>> fmt.Println(r)
>>> }
>>> }
>>> }
>>> 
>>> many thanks
>>> Chris
>>> -- 
>>> 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.
> -- 
> 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.


Re: [go-nuts] Channels: selecting the last element

2018-12-18 Thread Robert Engels
That code is incorrect as well when using buffered channels. 

> On Dec 18, 2018, at 10:00 AM, Skip Tavakkolian  
> wrote:
> 
> why not just  drop the select? i think the following is guaranteed because 
> putting things on rc has to succeed before putting true into dc:
> 
> package main
> 
> import (
>   "fmt"
> )
> 
> func do(i int, rc chan<- int, dc chan<- bool) {
>   rc <- i
>   dc <- true
> }
> 
> func main() {
>   worker := 10
>   rc := make(chan int, worker)
>   done := 0
>   dc := make(chan bool, worker)
>   for i := 0; i < worker; i++ {
>   go do(i, rc, dc)
>   }
>   for done < worker {
>   r := <-rc
>   fmt.Println(r)
>   <-dc
>   done++
>   }
> }
> 
> 
>> On Tue, Dec 18, 2018 at 5:35 AM Chris Burkert  
>> wrote:
>> Dear all,
>> 
>> I have a couple of goroutines sending multiple results over a channel - a 
>> simple fan-in. They signal the completion on a done channel. Main selects on 
>> the results and done channel in parallel. As the select is random main 
>> sometimes misses to select the last result. What would be the idiomatic way 
>> to prevent this and completely drain the result channel?
>> 
>> Here is a minmal example which sometimes prints one 0 but should always 
>> print two of them:
>> 
>> package main
>> 
>> import (
>> "fmt"
>> )
>> 
>> func do(rc chan<- int, dc chan<- bool) {
>> rc <- 0
>> dc <- true
>> }
>> 
>> func main() {
>> worker := 2
>> rc := make(chan int, worker)
>> done := 0
>> dc := make(chan bool, worker)
>> for i := 0; i < worker; i++ {
>> go do(rc, dc)
>> }
>> for done < worker {
>> select {
>> case <-dc:
>> done++
>> case r := <-rc:
>> fmt.Println(r)
>> }
>> }
>> }
>> 
>> many thanks
>> Chris
>> -- 
>> 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.

-- 
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] Channels: selecting the last element

2018-12-18 Thread Skip Tavakkolian
why not just  drop the select? i think the following is guaranteed because
putting things on rc has to succeed before putting true into dc:

package main

import (
"fmt"
)

func do(i int, rc chan<- int, dc chan<- bool) {
rc <- i
dc <- true
}

func main() {
worker := 10
rc := make(chan int, worker)
done := 0
dc := make(chan bool, worker)
for i := 0; i < worker; i++ {
go do(i, rc, dc)
}
for done < worker {
r := <-rc
fmt.Println(r)
<-dc
done++
}
}


On Tue, Dec 18, 2018 at 5:35 AM Chris Burkert 
wrote:

> Dear all,
>
> I have a couple of goroutines sending multiple results over a channel - a
> simple fan-in. They signal the completion on a done channel. Main selects
> on the results and done channel in parallel. As the select is random main
> sometimes misses to select the last result. What would be the idiomatic way
> to prevent this and completely drain the result channel?
>
> Here is a minmal example which sometimes prints one 0 but should always
> print two of them:
>
> package main
>
> import (
> "fmt"
> )
>
> func do(rc chan<- int, dc chan<- bool) {
> rc <- 0
> dc <- true
> }
>
> func main() {
> worker := 2
> rc := make(chan int, worker)
> done := 0
> dc := make(chan bool, worker)
> for i := 0; i < worker; i++ {
> go do(rc, dc)
> }
> for done < worker {
> select {
> case <-dc:
> done++
> case r := <-rc:
> fmt.Println(r)
> }
> }
> }
>
> many thanks
> Chris
>
> --
> 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.


Re: [go-nuts] Channels: selecting the last element

2018-12-18 Thread Ian Lance Taylor
On Tue, Dec 18, 2018 at 5:35 AM Chris Burkert  wrote:
>
> I have a couple of goroutines sending multiple results over a channel - a 
> simple fan-in. They signal the completion on a done channel. Main selects on 
> the results and done channel in parallel. As the select is random main 
> sometimes misses to select the last result. What would be the idiomatic way 
> to prevent this and completely drain the result channel?
>
> Here is a minmal example which sometimes prints one 0 but should always print 
> two of them:
>
> package main
>
> import (
> "fmt"
> )
>
> func do(rc chan<- int, dc chan<- bool) {
> rc <- 0
> dc <- true
> }
>
> func main() {
> worker := 2
> rc := make(chan int, worker)
> done := 0
> dc := make(chan bool, worker)
> for i := 0; i < worker; i++ {
> go do(rc, dc)
> }
> for done < worker {
> select {
> case <-dc:
> done++
> case r := <-rc:
> fmt.Println(r)
> }
> }
> }


I assume the workers can generate multiple results, as otherwise the
done marker seems pointless.  In general the simplest way to signal
completion on a channel is to call close.  The simplest way to call
close on a fan-in is to have another goroutine that waits for the
other goroutines and closes the channel.  That might look like

package main

import (
"fmt"
"sync"
)

func do(rc chan<- int) {
rc <- 0
}

func main() {
worker := 2
rc := make(chan int, worker)
var wg sync.WaitGroup
wg.Add(worker)
for i := 0; i < worker; i++ {
go func() {
defer wg.Done()
do(rc)
}()
}
go func() {
wg.Wait()
close(rc)
}()
for r := range rc {
fmt.Println(r)
}
}

Ian

-- 
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] Channels: selecting the last element

2018-12-18 Thread Burak Serdar
On Tue, Dec 18, 2018 at 6:35 AM Chris Burkert  wrote:
>
> Dear all,
>
> I have a couple of goroutines sending multiple results over a channel - a 
> simple fan-in. They signal the completion on a done channel. Main selects on 
> the results and done channel in parallel. As the select is random main 
> sometimes misses to select the last result. What would be the idiomatic way 
> to prevent this and completely drain the result channel?
>
> Here is a minmal example which sometimes prints one 0 but should always print 
> two of them:
>
> package main
>
> import (
> "fmt"
> )
>
> func do(rc chan<- int, dc chan<- bool) {
> rc <- 0
> dc <- true
> }
>
> func main() {
> worker := 2
> rc := make(chan int, worker)
> done := 0
> dc := make(chan bool, worker)
> for i := 0; i < worker; i++ {
> go do(rc, dc)
> }
> for done < worker {
> select {
> case <-dc:
> done++
> case r := <-rc:
> fmt.Println(r)
> }
> }
> }

You could change the message type, something like this:

type Msg struct {
  value int
  done bool
}

func do(rc chan<- Msg) {
 rc <- {value:-, done:true}
}

...

for done < worker {
  select {
  case r:=<-rc:
   if r.done {
 done++
   }
   }
}


>
> many thanks
> Chris
>
> --
> 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.


Re: [go-nuts] Channels: selecting the last element

2018-12-18 Thread Robert Engels
Thinking about it, use the expected count, in the done process decrement the 
count and only print when 0. Thus works if the channels are unbuffered. 


> On Dec 18, 2018, at 7:49 AM, Robert Engels  wrote:
> 
> This is not trivial, as you are imposing an order on unrelated async events. 
> 
> Would you phrase the condition as, do not process a done until I’ve processed 
> requests for N routines - then you are back to using an expected count. 
> 
> With an expected count, the problem is trivial.
> 
> I think you need to step back and decide what you are trying to parallelize.
> 
>> On Dec 18, 2018, at 7:34 AM, Chris Burkert  wrote:
>> 
>> Dear all,
>> 
>> I have a couple of goroutines sending multiple results over a channel - a 
>> simple fan-in. They signal the completion on a done channel. Main selects on 
>> the results and done channel in parallel. As the select is random main 
>> sometimes misses to select the last result. What would be the idiomatic way 
>> to prevent this and completely drain the result channel?
>> 
>> Here is a minmal example which sometimes prints one 0 but should always 
>> print two of them:
>> 
>> package main
>> 
>> import (
>> "fmt"
>> )
>> 
>> func do(rc chan<- int, dc chan<- bool) {
>> rc <- 0
>> dc <- true
>> }
>> 
>> func main() {
>> worker := 2
>> rc := make(chan int, worker)
>> done := 0
>> dc := make(chan bool, worker)
>> for i := 0; i < worker; i++ {
>> go do(rc, dc)
>> }
>> for done < worker {
>> select {
>> case <-dc:
>> done++
>> case r := <-rc:
>> fmt.Println(r)
>> }
>> }
>> }
>> 
>> many thanks
>> Chris
>> -- 
>> 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.

-- 
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] Channels: selecting the last element

2018-12-18 Thread Robert Engels
This is not trivial, as you are imposing an order on unrelated async events. 

Would you phrase the condition as, do not process a done until I’ve processed 
requests for N routines - then you are back to using an expected count. 

With an expected count, the problem is trivial.

I think you need to step back and decide what you are trying to parallelize.

> On Dec 18, 2018, at 7:34 AM, Chris Burkert  wrote:
> 
> Dear all,
> 
> I have a couple of goroutines sending multiple results over a channel - a 
> simple fan-in. They signal the completion on a done channel. Main selects on 
> the results and done channel in parallel. As the select is random main 
> sometimes misses to select the last result. What would be the idiomatic way 
> to prevent this and completely drain the result channel?
> 
> Here is a minmal example which sometimes prints one 0 but should always print 
> two of them:
> 
> package main
> 
> import (
> "fmt"
> )
> 
> func do(rc chan<- int, dc chan<- bool) {
> rc <- 0
> dc <- true
> }
> 
> func main() {
> worker := 2
> rc := make(chan int, worker)
> done := 0
> dc := make(chan bool, worker)
> for i := 0; i < worker; i++ {
> go do(rc, dc)
> }
> for done < worker {
> select {
> case <-dc:
> done++
> case r := <-rc:
> fmt.Println(r)
> }
> }
> }
> 
> many thanks
> Chris
> -- 
> 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.