Hi Marcin,

I think https://play.golang.org/p/RiKi1PGVSvF is basically what I do with 
atomic operations in my blog post 
https://dev.to/leolara/closing-a-go-channel-written-by-several-goroutines-52j2 
in 
the section "Some experiments", and then using the wait group as I say 
later in the section "The solution involves wait groups",

I think it is more constrained than my final solution because:
 + You need to make sure that all producers have started (run Add(1)) 
before you call Close. You would need to use a mutex around Add and Wait to 
solve this, I think now that a RWLock have the read arround Add(1) and the 
write around Wait could be better.
 + All writing goroutines will stay blocked until a reader reads all, using 
a closing channel is better because you can use select and they could 
unblock without a reader.


On Wednesday, August 28, 2019 at 10:37:52 PM UTC+2, Marcin Romaszewicz 
wrote:
>
> Think of a channel as existing for the lifetime of a particular data 
> stream, and not have it be associated with either producer or consumer. 
> Here's an example:
>
> https://play.golang.org/p/aEAXXtz2X1g
>
> The channel here is closed after all producers have exited, and all 
> consumers continue to run until the channel is drained of data.
>
> The producers are managed by something somewhere in your code - and that 
> is the scope at which it makes sense to create channel ownership. I've used 
> a waitgroup to ensure that the channel is closed after all producers exit, 
> but you can use whatever barrier construct you want.
>
> Even if you must have a channel per producer, you can safely close the 
> producer side, without notifying the downstream about this. The example 
> early in the thread uses multiple channels, with one channel being used to 
> signal that the producers should exit. Channels aren't really the right 
> model for this, you want a thread safe flag of some sort. For example:
>
> var exitFlag uint64
> func producer(chan data int, wg *sync.WaitGroup) {
>     defer wg.Done()
>     for {
>         shouldExit := atomic.LoadUint64(&exitFlag)
>         if shouldExit == 1 {
>              return
>         }
>         chan <- rand.Intn(100)
>     }
> }
>
> Here's 10 producers and 3 consumers sharing a channel and closing it 
> safely upon receiving an exit flag:
> https://play.golang.org/p/RiKi1PGVSvF
>
> -- Marcin
>
> On Wed, Aug 28, 2019 at 11:29 AM Leo Lara <l...@leopoldolara.com 
> <javascript:>> wrote:
>
>> I do not think priority select is *necessary*, it could be a nice 
>> addition if the performance does not change.
>>
>> On Wednesday, August 28, 2019 at 8:27:36 PM UTC+2, Leo Lara wrote:
>>>
>>> Hi Robert,
>>>
>>> From the article: """To bound more the problem, in my case, you control 
>>> the writers but not the readers"""
>>>
>>> So what I was trying to do was to be able to close, with mutiple 
>>> writers, while being transparent for the readers. The readers only need to 
>>> read as usual form the channel.
>>>
>>> For example, if you want to write a library where the user just reads 
>>> from a channel, this is an approach I found where the user of the lirbary 
>>> deos nto have to do anything special. Of course, there might be another 
>>> solution, but if you need to modify the reader we are talking about a 
>>> different problem.
>>>
>>> Cheers!!
>>>
>>> On Wednesday, August 28, 2019 at 7:17:24 PM UTC+2, Robert Engels wrote:
>>>>
>>>> A better solution is to wrap the writes using a RWLock, grab the read 
>>>> lock for writing, and the Write lock for closing. Pretty simple.
>>>>
>>>> Just encapsulate it all in a MultiWriterChannel struct - generics would 
>>>> help here :)
>>>>
>>>> -----Original Message----- 
>>>> From: Leo Lara 
>>>> Sent: Aug 28, 2019 11:24 AM 
>>>> To: golang-nuts 
>>>> Subject: [go-nuts] Re: An old problem: lack of priority select cases 
>>>>
>>>> This is connected with my article: 
>>>> https://dev.to/leolara/closing-a-go-channel-written-by-several-goroutines-52j2
>>>>
>>>> I think there I show it is possible to workaround that limitation using 
>>>> standard Go tools. Of course, the code would be simple with priority 
>>>> select, but also perhaps select would become less efficient.
>>>>
>>>> On Wednesday, August 28, 2019 at 6:06:33 PM UTC+2, T L wrote:
>>>>>
>>>>> The old thread: 
>>>>> https://groups.google.com/forum/#!topic/golang-nuts/ZrVIhHCrR9o
>>>>>
>>>>> Go channels are flexible, but in practice, I often encountered some 
>>>>> situations in which channel are hard to use.
>>>>> Given an example:
>>>>>
>>>>> import "math/rand"
>>>>>
>>>>> type Producer struct {
>>>>>     data   chan int
>>>>>     closed chan struct{}
>>>>> }
>>>>>
>>>>> func NewProducer() *Producer {
>>>>>     p := &Producer {
>>>>>         data:   make(chan int),
>>>>>         closed: make(chan struct{}),
>>>>>     }
>>>>>     
>>>>>     go p.run()
>>>>>     
>>>>>     return p
>>>>> }
>>>>>
>>>>> func (p *Produce) Stream() chan int {
>>>>>     return p.data
>>>>> }
>>>>>
>>>>> func (p *Producer) run() {
>>>>>     for {
>>>>>         // If non-blocking cases are selected by their appearance 
>>>>> order,
>>>>>         // then the following slect block is a perfect use.
>>>>>         select {
>>>>>         case(0) <-p.closed: return
>>>>>         case p.data <- rand.Int():
>>>>>         }
>>>>>     }
>>>>> }
>>>>>
>>>>> func (p *Produce) Clsoe() {
>>>>>     close(p.closed)
>>>>>     close(p.data)
>>>>> }
>>>>>
>>>>> func main() {
>>>>>     p := NewProducer()
>>>>>     for n := p.Stream() {
>>>>>         // use n ...
>>>>>     }
>>>>> }
>>>>>
>>>>>
>>>>> If the first case in the select block in the above example has a 
>>>>> higher priority than the second one,
>>>>> then coding will be much happier for the use cases like the above one.
>>>>>
>>>>> In short, the above use case requires:
>>>>> * for receivers, data streaming end is notified by the close of a 
>>>>> channel.
>>>>> * for senders, data will never be sent to closed channel.
>>>>>
>>>>> But, as Go 1 doesn't support priority select cases, it is much tedious 
>>>>> to implement the code
>>>>> satisfying the above listed requirements. The final implementation is 
>>>>> often very ugly and inefficient.
>>>>>
>>>>> Does anyone else also experience the pain?
>>>>>
>>>> -- 
>>>> 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 golan...@googlegroups.com.
>>>> To view this discussion on the web visit 
>>>> https://groups.google.com/d/msgid/golang-nuts/b284f880-034a-4721-8686-ef48d3e2c14c%40googlegroups.com
>>>>  
>>>> <https://groups.google.com/d/msgid/golang-nuts/b284f880-034a-4721-8686-ef48d3e2c14c%40googlegroups.com?utm_medium=email&utm_source=footer>
>>>> .
>>>>
>>>>
>>>>
>>>>
>>>> -- 
>> 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 golan...@googlegroups.com <javascript:>.
>> To view this discussion on the web visit 
>> https://groups.google.com/d/msgid/golang-nuts/aeb38a0a-8268-42d7-a8eb-ce5ef01c5380%40googlegroups.com
>>  
>> <https://groups.google.com/d/msgid/golang-nuts/aeb38a0a-8268-42d7-a8eb-ce5ef01c5380%40googlegroups.com?utm_medium=email&utm_source=footer>
>> .
>>
>

-- 
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.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/aedd5ef7-1663-4eb9-b86c-d12499d37b3d%40googlegroups.com.

Reply via email to