btc-crawl/queue.go

80 lines
1.2 KiB
Go
Raw Normal View History

package main
2014-05-10 20:48:33 -05:00
import "sync"
// TODO: Make this an interface and multiple implementations (Redis etc?)
2014-05-10 20:48:33 -05:00
type Queue struct {
sync.Mutex
2014-05-18 00:16:05 -05:00
storage []string
filter func(string) *string
count int
cond *sync.Cond
done <-chan struct{}
2014-05-10 20:48:33 -05:00
}
2014-05-18 00:16:05 -05:00
func NewQueue(filter func(string) *string, done <-chan struct{}) *Queue {
2014-05-10 20:48:33 -05:00
q := Queue{
2014-05-18 00:16:05 -05:00
storage: []string{},
filter: filter,
done: done,
2014-05-10 20:48:33 -05:00
}
q.cond = sync.NewCond(&q)
2014-05-10 20:48:33 -05:00
return &q
}
func (q *Queue) Add(item string) bool {
2014-05-18 00:16:05 -05:00
q.Lock()
r := q.filter(item)
if r == nil {
2014-05-18 00:16:05 -05:00
q.Unlock()
return false
2014-05-10 20:48:33 -05:00
}
q.storage = append(q.storage, *r)
q.count++
q.Unlock()
q.cond.Signal()
2014-05-10 20:48:33 -05:00
return true
}
2014-05-15 19:04:09 -05:00
func (q *Queue) Iter() <-chan string {
ch := make(chan string)
2014-05-15 19:04:09 -05:00
go func() {
2014-05-18 00:16:05 -05:00
<-q.done
q.cond.Signal() // Wake up to close the channel.
}()
2014-05-15 19:04:09 -05:00
go func() {
for {
q.Lock()
if len(q.storage) == 0 {
// Wait until next Add
q.cond.Wait()
if len(q.storage) == 0 {
// Queue is finished
close(ch)
2014-05-17 23:53:15 -05:00
q.Unlock()
return
}
}
r := q.storage[0]
q.storage = q.storage[1:]
q.Unlock()
ch <- r
}
2014-05-15 19:04:09 -05:00
}()
return ch
2014-05-10 20:48:33 -05:00
}
2014-05-15 19:59:01 -05:00
func (q *Queue) Count() int {
// Number of outputs produced.
return q.count
}