Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@jordanorelli
Created September 7, 2012 17:53
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jordanorelli/3668150 to your computer and use it in GitHub Desktop.
Save jordanorelli/3668150 to your computer and use it in GitHub Desktop.
an absurd queue implementation with higher-order channels
package main
import (
"fmt"
"math/rand"
"time"
)
type Queue struct {
data []interface{}
n int
cpop chan chan interface{}
cpush chan interface{}
}
func New(n int) *Queue {
q := &Queue{
data: make([]interface{}, 0, n),
cpop: make(chan chan interface{}),
cpush: make(chan interface{}),
}
go q.run()
return q
}
func (q *Queue) run() {
for {
select {
case c := <-q.cpop:
c <- q.pop()
case v := <-q.cpush:
q.push(v)
}
}
}
func (q *Queue) Push(v interface{}) {
q.cpush <- v
}
func (q *Queue) push(v interface{}) {
q.data = append(q.data, v)
}
func (q *Queue) Pop() (interface{}, bool) {
if len(q.data) == 0 {
return nil, false
}
c := make(chan interface{})
q.cpop <- c
return <-c, true
}
func (q *Queue) pop() interface{} {
if len(q.data) == 0 {
return nil
}
defer func() { q.data = q.data[1:] }()
return q.data[0]
}
func (q *Queue) Empty() bool {
return len(q.data) == 0
}
func main() {
q := New(100)
rand.Seed(time.Now().Unix())
// producer
go func() {
for {
switch rand.Intn(3) {
case 0:
q.Push(1)
case 1:
q.Push("stanley")
case 2:
q.Push(struct {
X int
Y int
}{
X: 5,
Y: 10,
})
}
time.Sleep(time.Millisecond * time.Duration(rand.Intn(10)))
}
}()
// consumer
for {
v, ok := q.Pop()
if ok {
fmt.Println(v)
}
time.Sleep(time.Millisecond * time.Duration(rand.Intn(10)))
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment