-
-
Save robbiev/1854d3fc9dcb7ae884423e39f93dc1e7 to your computer and use it in GitHub Desktop.
// SOLUTION 1 | |
// see https://groups.google.com/forum/#!topic/golang-nuts/ChPxr_h8kUM | |
func maybe(b bool, c chan int) chan int { | |
if !b { | |
return nil | |
} | |
return c | |
} | |
select { | |
case <-maybe(val>0, p): | |
val-- | |
case <-v: | |
val++ | |
} | |
// SOLUTION 2 | |
// see https://groups.google.com/forum/#!topic/golang-nuts/M2xjN_yWBiQ | |
select { | |
case <-higher: | |
foo() | |
default: | |
select { | |
case <-lower: | |
bar() | |
default: | |
... | |
} | |
} |
Those are both incorrect, at least in the case where you don't have defaults.
for {
select {
case <- higher:
processHigher()
case <- lower:
Lower:
for {
select {
case <- higher:
processHigher()
default:
break Lower
}
}
processLower()
}
The above will process higher & lower forever, but will only process lower if the is no higher available.
@muir Priority is only relevant when execution first hits this block.
If there is is data in higher
, process it first. Then, wait for data from either higher
or lower
.
If there is no data in either channel, wait for any data from either channel, and process whichever arrives first.
Even if higher
and lower
are written at roughly the same time, go will typically be allowed to reorder the reads, such that your solution does not make any stronger ordering guarantees.
The only exceptional case where your solution would behave differently is when there's a known happens-before
relationship between the writes to higher
and lower
, (guaranteeing that they occur in that order).
Very unusual to have events passed this way, & not something I'd want to rely on.
I'm not sure we're talking about the same problem so let's make sure of that first. I think the problem is: In a stream of events that might have gaps where there are no events, process higher priority events before processing lower priority events. Do not spin the CPU when there are no events.
Neither your code nor @robbiev 's #2 meet that criteria.
The behavior of #2 is:
- If there is a higher available right now then process it.
- If not, and there is a lower available right now then process it.
- If not, then exit the code (loop, function, etc)
If we put this code in a loop, it would spin the CPU when there were no events to read.
The behavior of your code is:
- If there is a higher available right now then process it.
- If not, then wait for either a higher or a lower to arrive and process whichever arrives first or pick one randomly if they both arrive at once.
- Then exit the code (loop, function, etc)
If we put your code in a loop, then it would only give preference to higher if there were higher waiting in the queue. That is a much weaker guarantee that what my code provides.
If default is not defined on the innermost select, it should include all previous cases, like:
Thus higher is prioritized, but any channel can trigger execution if none are ready initially.