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; if (!_timeouts.TryDequeue(out timeout) || timeout == null) { // all processed break; } if (timeout.State == HashedWheelTimeout.ST_CANCELLED) { // Was cancelled in the meantime. continue; } long calculated = timeout._deadline / _tickDuration; timeout._remainingRounds = (calculated - _tick) / _wheel.Length; long ticks = Math.Max(calculated, _tick); // Ensure we don't schedule for past. int stopIndex = (int)(ticks & _mask); HashedWheelBucket bucket = _wheel[stopIndex]; bucket.AddTimeout(timeout); } }
internal void Remove() { HashedWheelBucket bucket = _bucket; if (bucket != null) { bucket.Remove(this); } else { _timer.DescreasePendingTimeouts(); } }
private void Run() { // Initialize the startTime. _startTime = GetCurrentMs(); if (_startTime == 0) { // We use 0 as an indicator for the uninitialized value here, so make sure it's not 0 when initialized. _startTime = 1; } // Notify the other threads waiting for the initialization at start(). _startTimeInitialized.Set(); do { long deadline = WaitForNextTick(); if (deadline > 0) { int idx = (int)(_tick & _mask); ProcessCancelledTasks(); HashedWheelBucket bucket = _wheel[idx]; TransferTimeoutsToBuckets(); bucket.ExpireTimeouts(deadline); _tick++; } } while (_workerState == WORKER_STATE_STARTED); // Fill the unprocessedTimeouts so we can return them from stop() method. foreach (HashedWheelBucket bucket in _wheel) { bucket.ClearTimeouts(_unprocessedTimeouts); } for (; ;) { HashedWheelTimeout timeout; if (!_timeouts.TryDequeue(out timeout) || timeout == null) { break; } if (!timeout.Cancelled) { _unprocessedTimeouts.Add(timeout); } } ProcessCancelledTasks(); }
private static HashedWheelBucket[] CreateWheel(int ticksPerWheel) { if (ticksPerWheel <= 0) { throw new ArgumentOutOfRangeException(nameof(ticksPerWheel), "must be greater than 0"); } if (ticksPerWheel > 1073741824) { throw new ArgumentOutOfRangeException(nameof(ticksPerWheel), "may not be greater than 2^30"); } ticksPerWheel = NormalizeTicksPerWheel(ticksPerWheel); HashedWheelBucket[] wheel = new HashedWheelBucket[ticksPerWheel]; for (int i = 0; i < wheel.Length; i++) { wheel[i] = new HashedWheelBucket(); } return(wheel); }