package go9p type Log struct { Data interface{} Owner interface{} Type int } type Logger struct { items []*Log idx int logchan chan *Log fltchan chan *flt rszchan chan int } type flt struct { owner interface{} itype int fltchan chan []*Log } func NewLogger(sz int) *Logger { if sz == 0 { return nil } l := new(Logger) l.items = make([]*Log, sz) l.logchan = make(chan *Log, 16) l.fltchan = make(chan *flt) l.rszchan = make(chan int) go l.doLog() return l } func (l *Logger) Resize(sz int) { if sz == 0 { return } l.rszchan <- sz } func (l *Logger) Log(data, owner interface{}, itype int) { l.logchan <- &Log{data, owner, itype} } func (l *Logger) Filter(owner interface{}, itype int) []*Log { c := make(chan []*Log) l.fltchan <- &flt{owner, itype, c} return <-c } func (l *Logger) doLog() { for { select { case it := <-l.logchan: if l.idx >= len(l.items) { l.idx = 0 } l.items[l.idx] = it l.idx++ case sz := <-l.rszchan: it := make([]*Log, sz) for i, j := l.idx, 0; j < len(it); j++ { if i >= len(l.items) { i = 0 } it[j] = l.items[i] i++ if i == l.idx { break } } l.items = it l.idx = 0 case flt := <-l.fltchan: n := 0 // we don't care about the order while counting for _, it := range l.items { if it == nil { continue } if (flt.owner == nil || it.Owner == flt.owner) && (flt.itype == 0 || it.Type == flt.itype) { n++ } } its := make([]*Log, n) for i, m := l.idx, 0; m < len(its); i++ { if i >= len(l.items) { i = 0 } it := l.items[i] if it != nil && (flt.owner == nil || it.Owner == flt.owner) && (flt.itype == 0 || it.Type == flt.itype) { its[m] = it m++ } } flt.fltchan <- its } } }