"RecvExpr must be a receive operation. For all the cases in the
"select" statement, the channel expressions are evaluated in
top-to-bottom order, along with any expressions that appear on the
right hand side of send statements. A channel may be nil, which is
equivalent to that case not being present in the select statement
except, if a send, its expression is still evaluated. If any of the
resulting operations can proceed, one of those is chosen and the
corresponding communication and statements are evaluated. Otherwise,
if there is a default case, that executes; if there is no default
case, the statement blocks until one of the communications can
complete. If there are no cases with non-nil channels, the statement
blocks forever. Even if the statement blocks, the channel and send
expressions are evaluated only once, upon entering the select
statement."
This sounds like it might be a premature optimization, but you could do this in your loop:select {case val := <-high:continuedefault:}
select {case val := <-high:case val := <-low:}
Having said that though, what problem are you trying to solve with "prioritized" channels?
This sounds like it might be a premature optimization, but you could do this in your loop:select {case val := <-high:continuedefault:}
select {case val := <-high:case val := <-low:}Hmm, interesting, looks like this could work.
In its simplest form, a "for" statement specifies the repeated execution of a block as long as a boolean condition evaluates to true. The condition is evaluated before each iteration. If the condition is absent, it is equivalent totrue. [emphasis mine]
if select chose its items in order, it would be impossible to determine, for a given select statement, whether or not all of those channel reads would eventually be reached. That is, if you are selecting on two channels that are always ready, and it's non-random, only the first will ever be read from, and the second could be put into a state of isolation. Resource starvation could occur if simultaneous channel-selection operations were not randomized.
I struggle to see why one would want to prioritize their channel reads, because it seems liable to give you concurrency bugs, but, either way, here is how you would do it:high, low := make(chan whatever), make(chan whatever)go someFunc(high)go someOtherFunc(low)if v, ok := <-high; ok {use(v)} else {if v, ok := <-low; ok {use(v)} else {// no value on either channel}}
the concept of prioritizing channels makes my stomach uneasy. What's the use case?
...
Having said that though, what problem are you trying to solve with "prioritized" channels?
Hello,i wonder how to implement channel priorities nicely. Say there are two channels, one with a higher priority than the other, and a goroutine waiting for incoming data on these channels. I have read that select picks a random case when multiple channels are ready. I thought of nesting selects: putting the lower priority select in the default case of the higher priority select, and have the default case of the inner (low priority) select do nothing. This leads to a kind of busy wait loop. I could call a short sleep, but that still isn't very clean. Is there a better way?Why aren't the select cases evaluated in order?
--
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.
To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/CAJhgaciGHN633%2BCWtYE6Gw4i8pdB9XoQ5HbOiHR1X06oJxMdCQ%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.
This was my attempt at a channel with priorities:Based on the assumption that priorities only make sense if items are queued. If they are pulled out from a channel as fast as they are added to it, then there is no need for priorization.
On Fri, May 24, 2019 at 1:50 AM roger peppe <rogp...@gmail.com> wrote:On Thu, 23 May 2019 at 19:28, Bruno Albuquerque <b...@gmail.com> wrote:This was my attempt at a channel with priorities:Based on the assumption that priorities only make sense if items are queued. If they are pulled out from a channel as fast as they are added to it, then there is no need for priorization.I'm not entirely sure that's the right assumption. The original request is about having prioritybetween different channels. If there's a value available on both channels, you only ever want toprocess the high priority one. With your code, however, if you've got two goroutines sending and theoutput channel is always ready to receive, the priority is decided by goroutine scheduling, andthe low priority channel can win inappropriately: https://play.golang.org/p/YBD_w5vVqjt
My code actually uses a single channel and deals with relative priorities between items added to the channel. The original problem can be morphed to this by using only 2 priorities. I honestly do not think that worrying about 2 values being sent by 2 different go routines at nearly the same time is something one needs to worry about. This is similar to having 2 entries sent to individual channels at nearly the same time but with enough skew that the low priority one arrives before the higher priority one does (so it will be processed first unless there is a forced delay added (as seem on the other approach).
There is one big advantage with my solution: You can actually model any reasonable number of priorities you might need without any code changes whatsoever. It can handle 2 priorities as well as it can handle 100.
On Thu, 23 May 2019 at 19:28, Bruno Albuquerque <b...@gmail.com> wrote:This was my attempt at a channel with priorities:Based on the assumption that priorities only make sense if items are queued. If they are pulled out from a channel as fast as they are added to it, then there is no need for priorization.I'm not entirely sure that's the right assumption. The original request is about having prioritybetween different channels. If there's a value available on both channels, you only ever want toprocess the high priority one. With your code, however, if you've got two goroutines sending and theoutput channel is always ready to receive, the priority is decided by goroutine scheduling, andthe low priority channel can win inappropriately: https://play.golang.org/p/YBD_w5vVqjt
There are other issues too: the goroutine effectively acts as an infinite buffer, so any back pressure
from the output channel is lost; if you have a slow receiver, you could use a large amount of memory.Also, if the input channel is closed, your code will discard any values in the buffer: https://play.golang.org/p/5e_E17klnefYou perhaps want something a bit more like this: https://play.golang.org/p/hPHSRvpsqxa
FWIW the classical way to address the original problem in Go AIUI is to select on thehigh priority channels first (with a default clause), and then block on all the channels if there'snothing immediately ready. This idiom is a bit tedious to generalise to multiple channels (first select on c1, then c1, c2, then c1, c2, c3,etc until finally select on c1, ... cN), but isn't two bad with two.
On Fri, 24 May 2019 at 16:25, Bruno Albuquerque <b...@gmail.com> wrote:On Fri, May 24, 2019 at 1:50 AM roger peppe <rogp...@gmail.com> wrote:On Thu, 23 May 2019 at 19:28, Bruno Albuquerque <b...@gmail.com> wrote:This was my attempt at a channel with priorities:Based on the assumption that priorities only make sense if items are queued. If they are pulled out from a channel as fast as they are added to it, then there is no need for priorization.I'm not entirely sure that's the right assumption. The original request is about having prioritybetween different channels. If there's a value available on both channels, you only ever want toprocess the high priority one. With your code, however, if you've got two goroutines sending and theoutput channel is always ready to receive, the priority is decided by goroutine scheduling, andthe low priority channel can win inappropriately: https://play.golang.org/p/YBD_w5vVqjtMy code actually uses a single channel and deals with relative priorities between items added to the channel. The original problem can be morphed to this by using only 2 priorities. I honestly do not think that worrying about 2 values being sent by 2 different go routines at nearly the same time is something one needs to worry about. This is similar to having 2 entries sent to individual channels at nearly the same time but with enough skew that the low priority one arrives before the higher priority one does (so it will be processed first unless there is a forced delay added (as seem on the other approach).One example scenario when you might want to have priority receiving on two different channels (which was after all the question that started this thread), is when you're receiving messages from a high-volume buffered channel, and a low volume synchronous channel (for example, a channel returned from context.Done). If you get a value from the Done channel, you want to quit as soon as possible. If you just use a regular select, you can end up processing an unbounded number of messages before you decide to quit.
There is one big advantage with my solution: You can actually model any reasonable number of priorities you might need without any code changes whatsoever. It can handle 2 priorities as well as it can handle 100.If I may say so, there's one significant disadvantage of your solution: it doesn't solve the original problem :)
channels a,b,c of equal priority:pollorder = permute[a,b,c]channels a,b,c of priority a=5,b=2,c=1:
pollorder = permute[a,a,a,a,a b,b, c]
select {case msg1 := <-c1:fmt.Println("received", msg1)case msg1 := <-c1:fmt.Println("received", msg1)case msg2 := <-c2:fmt.Println("received", msg2)}
select {case msg1 := <-c1, <-c1:fmt.Println("received", msg1)case msg2 := <-c2:fmt.Println("received", msg2)}
g = gcd(list of priorities)
[list of priorities]/=g // defend against needless scales in priorities, ivy-like syntax
--
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.
To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/CAEd86Tym8dvnBHQj6Oudyc_K31-HgG-s4cQjB%3DbNzSpX11HKtw%40mail.gmail.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.
To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/CA%2B%3Diygt2bxH1E8fkD5JpPV1vKrz2ns%2BD5KpbhZ_SSm2vK%3Dds3w%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.
To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/CA%2B%3Diygt2bxH1E8fkD5JpPV1vKrz2ns%2BD5KpbhZ_SSm2vK%3Dds3w%40mail.gmail.com.