github.com/suiyunonghen/DxCommonLib@v0.5.3/TimeWheelingWorker.go_bak (about)

     1  /*
     2  时间轮询调度池,只用一个定时器来实现After等超时设定,默认轮渡器设定为1个小时,精度为500毫秒
     3  Autor: 不得闲
     4  QQ:75492895
     5  */
     6  package DxCommonLib
     7  
     8  import (
     9  	"sync"
    10  	"time"
    11  	"sync/atomic"
    12  )
    13  
    14  type (
    15  	TimeWheelWorker struct {
    16  		sync.Mutex                 //调度锁
    17  		ticker     *time.Ticker    //调度器时钟
    18  		timeslocks []chan struct{} //时间槽
    19  		slockcount int
    20  		maxTimeout time.Duration
    21  		quitchan   chan struct{}
    22  		curindex   int //当前的索引
    23  		interval   time.Duration
    24  		tkfunc		func()
    25  	}
    26  )
    27  
    28  var (
    29  	defaultTimeWheelWorker *TimeWheelWorker
    30      coarseTime 				atomic.Value		//存放的是当前的实际时间
    31  )
    32  
    33  //interval指定调度的时间间隔
    34  //slotBlockCount指定时间轮的块长度
    35  func NewTimeWheelWorker(interval time.Duration, slotBlockCount int,tkfunc func()) *TimeWheelWorker {
    36  	result := new(TimeWheelWorker)
    37  	result.interval = interval
    38  	result.quitchan = make(chan struct{})
    39  	result.slockcount = slotBlockCount
    40  	result.tkfunc = tkfunc
    41  	result.maxTimeout = interval * time.Duration(slotBlockCount)
    42  	result.timeslocks = make([]chan struct{}, slotBlockCount)
    43  	result.ticker = time.NewTicker(interval)
    44  	go result.run()
    45  	return result
    46  }
    47  
    48  func (worker *TimeWheelWorker) run() {
    49  	for {
    50  		select {
    51  		case <-worker.ticker.C:
    52  			//执行定时操作
    53  			//获取当前的时间槽数据
    54  			worker.Lock()
    55  			lastC := worker.timeslocks[worker.curindex]
    56  			worker.timeslocks[worker.curindex] = make(chan struct{})
    57  			worker.curindex = (worker.curindex + 1) % worker.slockcount
    58  			worker.Unlock()
    59  			if lastC != nil {
    60  				close(lastC)
    61  			}
    62  			if worker.tkfunc!=nil{
    63  				worker.tkfunc()
    64  			}
    65  		case <-worker.quitchan:
    66  			worker.ticker.Stop()
    67  			return
    68  		}
    69  	}
    70  }
    71  
    72  func (worker *TimeWheelWorker) Stop() {
    73  	close(worker.quitchan)
    74  }
    75  
    76  func (worker *TimeWheelWorker) After(d time.Duration) <-chan struct{} {
    77  	if d >= worker.maxTimeout {
    78  		panic("timeout too much, over maxtimeout")
    79  	}
    80  	index := int(d / worker.interval)
    81  	if index > 0 {
    82  		index--
    83  	}
    84  	worker.Lock()
    85  	index = (worker.curindex + index) % worker.slockcount
    86  	b := worker.timeslocks[index]
    87  	if b == nil {
    88  		b = make(chan struct{})
    89  		worker.timeslocks[index] = b
    90  	}
    91  	worker.Unlock()
    92  	return b
    93  }
    94  
    95  func (worker *TimeWheelWorker)AfterFunc(d time.Duration,afunc func())  {
    96  	select{
    97  	case <-worker.After(d):
    98  		afunc()
    99  	}
   100  }
   101  
   102  func (worker *TimeWheelWorker) Sleep(d time.Duration) {
   103  	select{
   104  	case <-worker.After(d):
   105  		return
   106  	}
   107  }
   108  
   109  func After(d time.Duration) <-chan struct{} {
   110  	return defaultTimeWheelWorker.After(d)
   111  }
   112  
   113  func AfterFunc(d time.Duration,afunc func()) {
   114  	defaultTimeWheelWorker.AfterFunc(d,afunc)
   115  }
   116  
   117  func Sleep(d time.Duration) {
   118  	defaultTimeWheelWorker.Sleep(d)
   119  }
   120  
   121  func ReSetDefaultTimeWheel(Chkinterval time.Duration,slotBlockCount int){
   122  	if defaultTimeWheelWorker.interval != Chkinterval  ||
   123  		defaultTimeWheelWorker.slockcount != slotBlockCount{
   124  			defaultTimeWheelWorker.Stop()
   125  			defaultTimeWheelWorker = NewTimeWheelWorker(Chkinterval, slotBlockCount, func() {
   126  				t := time.Now().Truncate(Chkinterval)
   127  				coarseTime.Store(&t)
   128  			})
   129  	}
   130  }
   131  
   132  
   133  func init()  {
   134  	defaultTimeWheelWorker = NewTimeWheelWorker(time.Millisecond*500, 7200, func() {
   135  		t := time.Now().Truncate(time.Millisecond*500)
   136  		coarseTime.Store(&t)
   137  	})
   138  	t := time.Now().Truncate(time.Millisecond*500)
   139  	coarseTime.Store(&t)
   140  }
   141  
   142  func CoarseTimeNow() time.Time {
   143  	tp := coarseTime.Load().(*time.Time)
   144  	return *tp
   145  }
   146