2014-07-10 12:19:39 +00:00
|
|
|
package main
|
|
|
|
|
2014-07-12 10:38:35 +00:00
|
|
|
import (
|
|
|
|
"sync"
|
|
|
|
)
|
2014-07-10 12:19:39 +00:00
|
|
|
|
|
|
|
const (
|
2014-09-09 08:20:40 +00:00
|
|
|
maxIndex = ^uint(0)
|
2014-07-10 12:19:39 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
type (
|
2014-07-15 19:41:38 +00:00
|
|
|
// Counter is responsible for operating queue read and write indexes
|
2014-09-09 08:20:40 +00:00
|
|
|
counter struct {
|
|
|
|
writeIndex uint // Number of the record last written to the queue
|
|
|
|
readIndex uint // Number of the record last read from the queue
|
2014-07-15 19:41:38 +00:00
|
|
|
// If WriteIndex is greater than ReadIndex then there are unread messages
|
|
|
|
// If WriteIndex is less tham ReadIndex then MaxIndex was reached
|
|
|
|
|
2014-09-09 08:20:40 +00:00
|
|
|
read chan uint
|
2014-07-15 19:41:38 +00:00
|
|
|
mutex sync.Mutex
|
2014-07-16 17:45:26 +00:00
|
|
|
streaming *sync.Cond
|
2014-07-10 12:19:39 +00:00
|
|
|
}
|
|
|
|
)
|
|
|
|
|
2014-09-09 08:20:40 +00:00
|
|
|
func newCounter(wi, ri uint) *counter {
|
2014-07-16 17:45:26 +00:00
|
|
|
m := &sync.Mutex{}
|
|
|
|
m.Lock()
|
|
|
|
|
2014-09-09 08:20:40 +00:00
|
|
|
c := &counter{
|
|
|
|
writeIndex: wi,
|
|
|
|
readIndex: ri,
|
|
|
|
read: make(chan uint),
|
2014-07-16 17:45:26 +00:00
|
|
|
streaming: sync.NewCond(m),
|
2014-07-12 10:38:35 +00:00
|
|
|
}
|
2014-07-16 17:45:26 +00:00
|
|
|
|
2014-09-09 08:20:40 +00:00
|
|
|
go c.stream()
|
2014-07-10 12:19:39 +00:00
|
|
|
return c
|
|
|
|
}
|
|
|
|
|
2014-09-09 08:20:40 +00:00
|
|
|
func (c *counter) write(proc func(i uint) bool) {
|
2014-07-12 10:38:35 +00:00
|
|
|
c.mutex.Lock()
|
|
|
|
defer c.mutex.Unlock()
|
|
|
|
|
2014-09-09 08:20:40 +00:00
|
|
|
ok := proc(c.writeIndex + 1)
|
2014-07-12 10:38:35 +00:00
|
|
|
if ok {
|
2014-09-09 08:20:40 +00:00
|
|
|
c.writeIndex++
|
2014-07-16 17:45:26 +00:00
|
|
|
c.streaming.Signal()
|
2014-07-10 12:19:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-09-09 08:20:40 +00:00
|
|
|
func (c *counter) distance() uint {
|
|
|
|
d := c.writeIndex - c.readIndex
|
2014-07-10 12:19:39 +00:00
|
|
|
if d < 0 {
|
2014-09-09 08:20:40 +00:00
|
|
|
d += maxIndex
|
2014-07-10 12:19:39 +00:00
|
|
|
}
|
|
|
|
return d
|
|
|
|
}
|
|
|
|
|
2014-09-09 08:20:40 +00:00
|
|
|
func (c *counter) stream() {
|
2014-07-16 17:45:26 +00:00
|
|
|
for {
|
2014-09-09 08:20:40 +00:00
|
|
|
if c.distance() == 0 {
|
2014-07-16 17:45:26 +00:00
|
|
|
c.streaming.Wait()
|
|
|
|
}
|
|
|
|
|
2014-09-09 08:20:40 +00:00
|
|
|
c.read <- c.readIndex + 1
|
|
|
|
c.readIndex++
|
2014-07-10 12:19:39 +00:00
|
|
|
}
|
|
|
|
}
|