On Wednesday, August 28, 2019 at 10:05:06 PM UTC-4, robert engels wrote: > > Here is a version using RWLock https://play.golang.org/p/YOwuYFiqtlf >
Doesn't the Read method need to be guarded by the reader lock? > > It won’t run correctly in the playground because it terminates when all > routines are asleep - which happens during the test (not sure why it does > this, as sleeping is different than a deadlock). > > It is probably less efficient, and less orderly than the other example > using WaitGroup but you get the idea I hope. It forcibly terminates the > writers before they complete by design. > > On Aug 28, 2019, at 4:09 PM, Michel Levieux <m.le...@capitaldata.fr > <javascript:>> wrote: > > One should also be careful regarding the conceptual demands he or she is > making. > Having a shared resource (that is complex enough that it cannot be > atomically accessed or modified) means essentially that "having multiple > writers being transparent to the readers", fundamentally, is not possible. > > From the moment itself when such a resource is shared, there must be some > sort of mecanism (that one using resources atomically usable) that ensures > the integrity of it. > Maybe what you're talking about is having it transparent in terms of code, > in which case we both agree, but if you're looking for something > transparent in essence, as in performance, logical construction and all the > rest, I think there is a misunderstanding here: even if it was added in the > language, there would be many many things going on under the hood, as it is > already (and cannot really be otherwise) for channel use alone. > > As for the priority using selects, I think it's more of something to be > dealt with on the "user-side". There are many kinds of priority in general, > and trying to implement something in the language itself would IMO either > be too specific compared to the nessecary time to do so or it would > probably have a huge overhead on the "classical' use case of the select > construct. > + the fact that it is apparently already possible using RWMutexes. > > Le mer. 28 août 2019 à 22:37, Marcin Romaszewicz <mar...@gmail.com > <javascript:>> a écrit : > >> 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 golan...@googlegroups.com <javascript:>. >> To view this discussion on the web visit >> https://groups.google.com/d/msgid/golang-nuts/CA%2Bv29LvcUhUvrZb_8AKYWj0A%2Bqd5LKBPmbz-RVBb%3DJn_gNZE6w%40mail.gmail.com >> >> <https://groups.google.com/d/msgid/golang-nuts/CA%2Bv29LvcUhUvrZb_8AKYWj0A%2Bqd5LKBPmbz-RVBb%3DJn_gNZE6w%40mail.gmail.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/CANgi337s1Low95QvqJUAOTsqcVji7uMQ_jr%3DFftpt2uMz5_XSQ%40mail.gmail.com > > <https://groups.google.com/d/msgid/golang-nuts/CANgi337s1Low95QvqJUAOTsqcVji7uMQ_jr%3DFftpt2uMz5_XSQ%40mail.gmail.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/a5cff3f8-cc1c-4719-9f2f-7b9c31086f6a%40googlegroups.com.