package common import ( "container/list" "sync" ) // LockList list type LockList struct { cache *list.List cv *sync.Cond cond bool size int } // NewLockList new func NewLockList(size int) *LockList { return &LockList{ cache: list.New(), cv: sync.NewCond(&sync.Mutex{}), cond: false, size: size, } } // Push push func (l *LockList) Push(v interface{}) { l.cv.L.Lock() l.cache.PushBack(v) for l.cache.Len() > l.size { l.cache.Remove(l.cache.Front()) } l.cond = true l.cv.Signal() l.cv.L.Unlock() } // Pop pop func (l *LockList) Pop() []interface{} { var batch []interface{} l.cv.L.Lock() for !l.cond { l.cv.Wait() } elem := l.cache.Front() if elem != nil { batch = append(batch, elem.Value) l.cache.Remove(l.cache.Front()) } l.cond = false l.cv.L.Unlock() return batch } // Drain drain all element func (l *LockList) Drain() []interface{} { var batch []interface{} l.cv.L.Lock() for !l.cond { l.cv.Wait() } for { elem := l.cache.Front() if elem == nil { break } batch = append(batch, elem.Value) l.cache.Remove(l.cache.Front()) } l.cond = false l.cv.L.Unlock() return batch }