private void transferTimeoutsToBuckets() { // transfer only max. 100000 timeouts per tick to prevent a thread to stale the workerThread when it just // adds new timeouts in a loop. for (int i = 0; i < 100000; i++) { HashedWheelTimeout timeout = null; if (!_timer._timeouts.TryDequeue(out timeout)) { // all processed break; } if (timeout.State == HashedWheelTimeout.ST_CANCELLED || !timeout.CompareAndSetState(HashedWheelTimeout.ST_INIT, HashedWheelTimeout.ST_IN_BUCKET)) { // Was cancelled in the meantime. So just remove it and continue with next HashedWheelTimeout // in the queue timeout.Remove(); continue; } long calculated = timeout.Deadline / this._timer._tickDurationTicks; long remainingRounds = (calculated - tick) / this._timer._wheel.Length; timeout.RemainingRounds = remainingRounds; long ticks = Math.Max(calculated, tick); // Ensure we don't schedule for past. int stopIndex = (int)(ticks & this._timer._mask); HashedWheelBucket bucket = _timer._wheel[stopIndex]; bucket.addTimeout(timeout); } }
/// <summary> /// 创建时间轮刻度上的桶。 /// </summary> private static HashedWheelBucket[] CreateWheel(int ticksPerWheel) { if (ticksPerWheel <= 0) { throw new ArgumentOutOfRangeException( "ticksPerWheel 必须大于 0,实际值:" + ticksPerWheel); } if (ticksPerWheel > 1073741824) { throw new ArgumentOutOfRangeException( "ticksPerWheel 不能大于 2^30,实际值:" + ticksPerWheel); } ticksPerWheel = NormalizeTicksPerWheel(ticksPerWheel); HashedWheelBucket[] wheel = new HashedWheelBucket[ticksPerWheel]; for (int i = 0; i < wheel.Length; i++) { wheel[i] = new HashedWheelBucket(); } return(wheel); }
public void Run() { // Initialize the startTime. _timer.startTime = System.DateTime.UtcNow.Ticks; if (_timer.startTime == 0) { // We use 0 as an indicator for the uninitialized value here, so make sure it's not 0 when initialized. _timer.startTime = 1; } // Notify the other threads waiting for the initialization at start(). _timer._startTimeInitialized.Set(); _waitHandler.Reset(); do { long deadline = WaitForNextTick(); //运行被中断。 if (deadline > 0) { transferTimeoutsToBuckets(); HashedWheelBucket bucket = _timer._wheel[(int)(tick & _timer._mask)]; bucket.ExpireTimeouts(deadline); tick++; } } while (Interlocked.Read(ref this._timer.workerState) == WORKER_STATE_STARTED); // Fill the unprocessedTimeouts so we can return them from stop() method. foreach (HashedWheelBucket bucket in _timer._wheel) { bucket.ClearTimeouts(unprocessedTimeouts); } HashedWheelTimeout timeout = null; while (_timer._timeouts.TryDequeue(out timeout)) { unprocessedTimeouts.Add(timeout); } }