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);
                }
            }
Example #2
0
        /// <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);
                }
            }