func SetTimerBacklog(c int) {
	if c < 16 {
		c = 16
	}
	timerBacklog = c
}
SetTimerBacklog set the timer created/closing channel backlog, A small backlog
may cause the logic to be blocked when call NewTimer/NewCountTimer/timer.Stop
in main logic gorontine.
package timer
import (
	"sync"
	"sync/atomic"
	"time"
	"github.com/topfreegames/pitaya/logger"
)
var timerBacklog int
const (
	LoopForever = -1
)
var (
	Manager = &struct {
		incrementID    int64       
		timers         sync.Map    
		ChClosingTimer chan int64  
		ChCreatedTimer chan *Timer
	}{}
	Precision = time.Second
	GlobalTicker *time.Ticker
)
type (
	Func func()
	Condition interface {
		Check(now time.Time) bool
	}
	Timer struct {
		ID        int64          
		fn        Func           
		createAt  int64          
		interval  time.Duration  
		condition Condition      
		elapse    int64          
		closed    int32          
		counter   int            
	}
)
func init() {
	timerBacklog = 1 << 8  
	Manager.ChClosingTimer = make(chan int64, timerBacklog)
	Manager.ChCreatedTimer = make(chan *Timer, timerBacklog)
}
func AddTimer(t *Timer) {
	Manager.timers.Store(t.ID, t)
}
func RemoveTimer(id int64) {
	Manager.timers.Delete(id)
}
func NewTimer(fn Func, interval time.Duration, counter int) *Timer {
	id := atomic.AddInt64(&Manager.incrementID, 1)
	t := &Timer{
		ID:       id,
		fn:       fn,
		createAt: time.Now().UnixNano(),
		interval: interval,
		elapse:   int64(interval),  
		counter:  counter,
	}
	Manager.ChCreatedTimer <- t
	return t
}
func (t *Timer) SetCondition(condition Condition) {
	t.condition = condition
}
func (t *Timer) Stop() {
	if atomic.LoadInt32(&t.closed) > 0 {
		return
	}
	if len(Manager.ChClosingTimer) < timerBacklog {
		Manager.ChClosingTimer <- t.ID
		atomic.StoreInt32(&t.closed, 1)
	} else {
		t.counter = 0  
	}
}
func pexec(id int64, fn Func) {
	defer func() {
		if err := recover(); err != nil {
			logger.Log.Errorf("Call timer function error, TimerID=%d, Error=%v", id, err)
		}
	}()
	fn()
}
func Cron() {
	now := time.Now()
	unn := now.UnixNano()
	Manager.timers.Range(func(idInterface, tInterface interface{}) bool {
		t := tInterface.(*Timer)
		id := idInterface.(int64)
		if t.counter == 0 {
			if len(Manager.ChClosingTimer) < timerBacklog {
				t.Stop()
			}
			return true
		}
		if t.condition != nil {
			if t.condition.Check(now) {
				pexec(id, t.fn)
			}
			return true
		}
		if t.createAt+t.elapse <= unn {
			pexec(id, t.fn)
			t.elapse += int64(t.interval)
			if t.counter != LoopForever && t.counter > 0 {
				t.counter--
			}
		}
		return true
	})
}