Skip to content

Instantly share code, notes, and snippets.

@kamal-github
Last active November 22, 2020 08:27
Show Gist options
  • Save kamal-github/4059db70407f6e20cee8478da6f52a18 to your computer and use it in GitHub Desktop.
Save kamal-github/4059db70407f6e20cee8478da6f52a18 to your computer and use it in GitHub Desktop.
Or Done channel - Concurrency in Go Book
package main
import (
"fmt"
"time"
)
// Simpler version for Or
func OrVer2(ch ...chan struct{}) <-chan struct{} {
switch len(ch) {
case 0:
return nil
case 1:
return ch[0]
}
orDone := make(chan struct{})
go func() {
defer close(orDone)
switch len(ch) {
case 2:
select {
case <-ch[0]:
case <-ch[1]:
}
default:
select {
case <-ch[0]:
case <-ch[1]:
case <-OrVer2(ch[2:]...):
}
}
}()
return orDone
}
func Or(ch ...chan struct{}) <-chan struct{} {
switch len(ch) {
case 0:
return nil
case 1:
return ch[0]
}
orDone := make(chan struct{})
go func() {
defer close(orDone)
switch len(ch) {
case 2:
select {
case <-ch[0]:
case <-ch[1]:
}
default:
select {
case <-ch[0]:
case <-ch[1]:
case <-ch[2]:
case <-Or(append(ch[3:], orDone)...):
}
}
}()
return orDone
}
func closeAfter(duration time.Duration) chan struct{} {
c := make(chan struct{})
go func() {
defer close(c)
time.Sleep(duration)
}()
return c
}
func main() {
startTime := time.Now()
<-OrVer2(
closeAfter(time.Hour),
closeAfter(time.Minute),
closeAfter(time.Second),
closeAfter(2*time.Second),
closeAfter(3*time.Second),
closeAfter(1*time.Second),
closeAfter(2*time.Second),
closeAfter(3*time.Minute),
closeAfter(5*time.Millisecond),
closeAfter(3*time.Second),
closeAfter(30*time.Second),
closeAfter(3*time.Second),
closeAfter(2*time.Second),
)
fmt.Println("Done in ", time.Since(startTime))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment