| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121 |
- // Copyright 2016 The G3N Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style
- // license that can be found in the LICENSE file.
- package core
- import (
- "time"
- )
- type TimerManager struct {
- nextID int // next timer id
- timers []timeout // list of timeouts
- }
- // Type for timer callback functions
- type TimerCallback func(interface{})
- // Internal structure for each active timer
- type timeout struct {
- id int // timeout id
- expire time.Time // expiration time
- period time.Duration // period time
- cb TimerCallback // callback function
- arg interface{} // callback function argument
- }
- // NewTimerManager creates and returns a new timer manager
- func NewTimerManager() *TimerManager {
- tm := new(TimerManager)
- tm.Initialize()
- return tm
- }
- // Initialize initializes the timer manager.
- // It is normally used when the TimerManager is embedded in another type.
- func (tm *TimerManager) Initialize() {
- tm.nextID = 1
- tm.timers = make([]timeout, 0)
- }
- // SetTimeout sets a timeout with the specified duration and callback
- // The function returns the timeout id which can be used to cancel the timeout
- func (tm *TimerManager) SetTimeout(td time.Duration, arg interface{}, cb TimerCallback) int {
- return tm.setTimer(td, false, arg, cb)
- }
- // SetInterval sets a periodic timeout with the specified duration and callback
- // The function returns the timeout id which can be used to cancel the timeout
- func (tm *TimerManager) SetInterval(td time.Duration, arg interface{}, cb TimerCallback) int {
- return tm.setTimer(td, true, arg, cb)
- }
- // ClearTimeout clears the timeout specified by the id.
- // Returns true if the timeout is found.
- func (tm *TimerManager) ClearTimeout(id int) bool {
- for pos, t := range tm.timers {
- if t.id == id {
- copy(tm.timers[pos:], tm.timers[pos+1:])
- tm.timers[len(tm.timers)-1] = timeout{}
- tm.timers = tm.timers[:len(tm.timers)-1]
- return true
- }
- }
- return false
- }
- // ProcessTimers should be called periodically to process the timers
- func (tm *TimerManager) ProcessTimers() {
- now := time.Now()
- for pos, t := range tm.timers {
- // If empty entry, ignore
- if t.id == 0 {
- continue
- }
- // Checks if entry expired
- if now.After(t.expire) {
- if t.period == 0 {
- tm.timers[pos] = timeout{}
- } else {
- tm.timers[pos].expire = now.Add(t.period)
- }
- t.cb(t.arg)
- }
- }
- }
- // setTimer sets a new timer with the specified duration
- func (tm *TimerManager) setTimer(td time.Duration, periodic bool, arg interface{}, cb TimerCallback) int {
- // Creates timeout entry
- t := timeout{
- id: tm.nextID,
- expire: time.Now().Add(td),
- cb: cb,
- arg: arg,
- period: 0,
- }
- if periodic {
- t.period = td
- }
- tm.nextID++
- // Look for empty entry
- for pos, ct := range tm.timers {
- if ct.id == 0 {
- tm.timers[pos] = t
- return t.id
- }
- }
- // If no empty entry found, add to end of array
- tm.timers = append(tm.timers, t)
- return t.id
- }
|