123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141 |
- package otherutils
- import (
- "sync"
- "time"
- )
- type event struct {
- timer *time.Timer
- ticker *time.Ticker
- endtime time.Time
- duration time.Duration
- parameter interface{}
- }
- func (e *event) expire() bool {
- if e.timer != nil {
- select {
- case <-e.timer.C:
- return true
- default:
- }
- }
- if e.ticker != nil {
- select {
- case <-e.ticker.C:
- return true
- default:
- }
- }
- return false
- }
- // Scheduler 调度程序
- type Scheduler interface {
- OnTimer(id int, parameter interface{})
- }
- // Schedule 时间表
- // 定时时间精确到秒,不精确管理goroutine的退出
- // 目前只用来管理房间
- type Schedule struct {
- scheduler Scheduler
- mutex sync.Mutex
- events map[int]*event
- }
- // NewSchedule 创建时间表
- func NewSchedule(scheduler Scheduler) *Schedule {
- return &Schedule{
- scheduler: scheduler,
- events: make(map[int]*event),
- }
- }
- // Start 开始
- func (s *Schedule) Start() {
- for {
- time.Sleep(time.Second)
- s.mutex.Lock()
- for k, v := range s.events {
- if v.expire() {
- if v.timer != nil {
- delete(s.events, k)
- }
- if v.ticker != nil {
- v.endtime = v.endtime.Add(v.duration)
- }
- go s.scheduler.OnTimer(k, v.parameter)
- }
- }
- s.mutex.Unlock()
- }
- }
- // Add 添加
- func (s *Schedule) Add(id int, duration time.Duration, parameter interface{}, persistence bool) {
- s.mutex.Lock()
- defer s.mutex.Unlock()
- ev, ok := s.events[id]
- if ok {
- if ev.timer == nil {
- return
- }
- if !ev.timer.Stop() {
- <-ev.timer.C // 必须这样做,不然Reset之后有可能立刻到期
- }
- ev.timer.Reset(duration)
- } else {
- ev = new(event)
- s.events[id] = ev
- if !persistence {
- ev.timer = time.NewTimer(duration)
- } else {
- ev.ticker = time.NewTicker(duration)
- }
- }
- ev.duration = duration
- ev.parameter = parameter
- ev.endtime = time.Now().Add(duration)
- }
- // Remove 移除
- func (s *Schedule) Remove(id int) {
- s.mutex.Lock()
- defer s.mutex.Unlock()
- if ev, ok := s.events[id]; ok {
- if ev.timer != nil && !ev.timer.Stop() {
- <-ev.timer.C
- }
- if ev.ticker != nil {
- ev.ticker.Stop()
- }
- delete(s.events, id)
- }
- }
- // Surplus 剩余
- func (s *Schedule) Surplus(id int) (duration time.Duration) {
- s.mutex.Lock()
- defer s.mutex.Unlock()
- if ev, ok := s.events[id]; ok {
- duration = ev.endtime.Sub(time.Now())
- }
- if duration < 0 {
- duration = 0
- }
- return
- }
|