/// <summary> /// 外部调用,每隔一定的时间Tick一次 /// </summary> public virtual void Tick() { if (mIsPaused) { return; } uint now = GetCurrentMillisecond(); uint loopNum = now > mCheckTime ? (now - mCheckTime) / Granularity : 0; TimeWheel wheel = mTimeWheels[0]; for (uint i = 0; i < loopNum; ++i) { LinkedList <TimerNode> spoke; if (wheel.TryGetSpoke((int)wheel.CurrentSpokeIndex, out spoke)) { for (var timerNodeHost = spoke.First; timerNodeHost != null;) { var nextTimerNodeHost = timerNodeHost.Next; timerNodeHost.List.Remove(timerNodeHost); timerNodeHost.Value.TimerNodeHost = null; --mTotalTimerNum; AddToReadyList(timerNodeHost); timerNodeHost = nextTimerNodeHost; } } mCheckTime += Granularity; ++wheel.CurrentSpokeIndex; if (wheel.CurrentSpokeIndex >= wheel.MaxSpokes) { wheel.CurrentSpokeIndex = 0; Cascade(1); } } DoTimeoutCallback(); if (mAutoPauseMode && mTotalTimerNum <= 0) { Pause(); } }
protected TimerManager(uint granularity = 20) { if (granularity <= 0) { throw new Exception("Granularity must be > 0"); } Granularity = granularity; mAutoPauseMode = true; mTimeWheels = new TimeWheel[5]; mTimeWheels[0] = new TimeWheel(256); for (int i = 1; i < 5; ++i) { mTimeWheels[i] = new TimeWheel(64); } mReadyToInvokeList = new LinkedList <TimerNode>(); mTimerNodeCache = new Stack <TimerNode>(); }
/// <summary> /// 上一个时间轮转过一轮后,检索下一个时间轮当前插槽中的定时器 /// </summary> /// <param name="wheelIndex"></param> protected virtual void Cascade(uint wheelIndex) { if (wheelIndex < 1 || wheelIndex >= 5) { return; } TimeWheel wheel = mTimeWheels[wheelIndex]; int currentSpokeIndex = (int)wheel.CurrentSpokeIndex; ++wheel.CurrentSpokeIndex; LinkedList <TimerNode> spoke; if (wheel.TryGetSpoke(currentSpokeIndex, out spoke)) { for (var timerNodeHost = spoke.First; timerNodeHost != null;) { var nextTimerNodeHost = timerNodeHost.Next; timerNodeHost.List.Remove(timerNodeHost); var timerNode = timerNodeHost.Value; --mTotalTimerNum; if (timerNode.DeadTime <= mCheckTime) { timerNode.TimerNodeHost = null; AddToReadyList(timerNodeHost); } else { AddTimerNode(timerNode.DeadTime - mCheckTime, timerNode); } timerNodeHost = nextTimerNodeHost; } } if (wheel.CurrentSpokeIndex >= wheel.MaxSpokes) { wheel.CurrentSpokeIndex = 0; Cascade(++wheelIndex); } }