package main import ( "log" "sync" "time" ) type DistEvent interface { GetId() int64 GetDate() *time.Time } // distList maintain a nextSettingsFile list up-to-date. type distList struct { List []DistEvent Lock sync.RWMutex Timer *time.Timer } func (l *distList) TimerNextEvent() *time.Timer { l.Lock.RLock() defer l.Lock.RUnlock() var min *time.Time for _, f := range l.List { if min == nil || f.GetDate().Before(*min) { min = f.GetDate() } } if min == nil { return nil } return time.NewTimer(time.Until(*min)) } func (l *distList) AddEvent(nsf DistEvent, firstItemChanged func(DistEvent)) { l.Lock.Lock() istop := len(l.List) for i, n := range l.List { if n.GetId() == nsf.GetId() { l.Lock.Unlock() return } else if n.GetDate().After(*nsf.GetDate()) { istop = i break } } l.List = append(l.List, nsf) copy(l.List[istop+1:], l.List[istop:]) l.List[istop] = nsf l.Lock.Unlock() if istop == 0 { l.ResetTimer() if firstItemChanged != nil { firstItemChanged(nsf) } } } func (l *distList) DelEvent(id int64, firstItemChanged func(DistEvent)) { l.Lock.Lock() istop := len(l.List) for i, n := range l.List { if n.GetId() == id { istop = i break } } if istop == len(l.List)-1 { l.List = l.List[:istop] } else if istop != len(l.List) { l.List = append(l.List[:istop], l.List[istop+1:]...) } l.Lock.Unlock() if istop == 0 { l.ResetTimer() if firstItemChanged != nil { if len(l.List) == 0 { firstItemChanged(nil) } else { firstItemChanged(l.List[0]) } } } } func (l *distList) ResetTimer() { l.Lock.RLock() defer l.Lock.RUnlock() if len(l.List) == 0 { l.Timer.Reset(time.Minute) } else { l.Timer.Reset(time.Until(*l.List[0].GetDate())) } } func (l *distList) Pop() DistEvent { l.Lock.Lock() defer l.Lock.Unlock() if len(l.List) == 0 { return nil } if time.Now().Before(*l.List[0].GetDate()) { return nil } ret := l.List[0] l.List = l.List[1:] return ret } func (l *distList) Print() { l.Lock.RLock() defer l.Lock.RUnlock() for n, i := range l.List { log.Printf("#%d: %v", n, i) } }