Skip to content

Instantly share code, notes, and snippets.

@aht
Created February 20, 2010 15:41
Show Gist options
  • Save aht/309734 to your computer and use it in GitHub Desktop.
Save aht/309734 to your computer and use it in GitHub Desktop.
import "container/ring"
// Use a goroutine to receive values from `out` and store them
// in an auto-expanding buffer, so that sending to `out` never blocks.
// Return a channel which serves as a sending proxy to to `out`.
func sendproxy(out chan<- int) chan<- int {
in := make(chan int, 100)
go func() {
n := 1000 // the allocated length of the circular queue
first := ring.New(n)
last := first
var c chan<- int
var e int
var ok bool
for {
select {
case e = <-in:
for added := 0; added < 1000; added++ {
if closed(in) {
in = nil
break
}
last.Value = e
if last.Next() == first {
// buffer full: expand it
last.Link(ring.New(n))
n *= 2
}
last = last.Next()
if e, ok = <-in; !ok {
break
}
}
c = out // enable output
e = first.Value.(int)
case c <- e:
for {
first = first.Next()
if first == last {
// buffer empty: disable output
if in == nil {
close(out)
return
}
c = nil
break
}
e = first.Value.(int)
if ok = c <- e; !ok {
break
}
}
}
}
}()
return in
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment