Ejemplo n.º 1
0
        /// <summary>
        /// Expire all HashedWheelTimeout for the given deadline.
        /// </summary>
        /// <param name="deadline"></param>
        internal void ExpireTimeouts(long deadline)
        {
            HashedWheelTimeout timeout = _head;

            // process all timeouts
            while (timeout != null)
            {
                HashedWheelTimeout next = timeout._next;
                if (timeout._remainingRounds <= 0)
                {
                    next = Remove(timeout);
                    if (timeout._deadline <= deadline)
                    {
                        timeout.Expire();
                    }
                    else
                    {
                        // The timeout was placed into a wrong slot. This should never happen.
                        throw new InvalidOperationException($"timeout.deadline ({timeout._deadline}) > deadline ({deadline})");
                    }
                }
                else if (timeout.Cancelled)
                {
                    next = Remove(timeout);
                }
                else
                {
                    timeout._remainingRounds--;
                }
                timeout = next;
            }
        }
Ejemplo n.º 2
0
        private HashedWheelTimeout PollTimeout()
        {
            var head = _head;

            if (head == null)
            {
                return(null);
            }

            var next = head.Next;

            if (next == null)
            {
                _tail = _head = null;
            }
            else
            {
                _head     = next;
                next.Prev = null;
            }

            // null out prev and next to allow for GC.
            head.Next   = null;
            head.Prev   = null;
            head.Bucket = null;
            return(head);
        }
Ejemplo n.º 3
0
        private HashedWheelTimeout PollTimeout()
        {
            HashedWheelTimeout head = this._head;

            if (head == null)
            {
                return(null);
            }
            HashedWheelTimeout next = head._next;

            if (next == null)
            {
                _tail = this._head = null;
            }
            else
            {
                this._head = next;
                next._prev = null;
            }

            // null out prev and next to allow for GC.
            head._next   = null;
            head._prev   = null;
            head._bucket = null;
            return(head);
        }
Ejemplo n.º 4
0
 public void AddTimeout(HashedWheelTimeout timeout)
 {
     timeout.Bucket = this;
     if (_head == null)
     {
         _head = _tail = timeout;
     }
     else
     {
         _tail.Next   = timeout;
         timeout.Prev = _tail;
         _tail        = timeout;
     }
 }
Ejemplo n.º 5
0
 internal void ClearTimeouts(ISet <Timeout> set)
 {
     for (; ;)
     {
         HashedWheelTimeout timeout = PollTimeout();
         if (timeout == null)
         {
             return;
         }
         if (timeout.Expired || timeout.Cancelled)
         {
             continue;
         }
         set.Add(timeout);
     }
 }
Ejemplo n.º 6
0
        public HashedWheelTimeout Remove(HashedWheelTimeout timeout)
        {
            var next = timeout.Next;

            // remove timeout that was either processed or cancelled by updating the linked-list
            if (timeout.Prev != null)
            {
                timeout.Prev.Next = next;
            }

            if (timeout.Next != null)
            {
                timeout.Next.Prev = timeout.Prev;
            }

            if (timeout == _head)
            {
                // if timeout is also the tail we need to adjust the entry too
                if (timeout == _tail)
                {
                    _tail = null;
                    _head = null;
                }
                else
                {
                    _head = next;
                }
            }
            else if (timeout == _tail)
            {
                // if the timeout is the tail modify the tail to be the prev node.
                _tail = timeout.Prev;
            }

            // null out prev, next and bucket to allow for GC.
            timeout.Prev   = null;
            timeout.Next   = null;
            timeout.Bucket = null;
            timeout.DecrementPendingTimeouts();
            return(next);
        }
        /// <summary>
        /// Schedules the specified TimerTask for one-time execution after the specified delay.
        /// </summary>
        /// <param name="task"></param>
        /// <param name="span"></param>
        /// <returns>a handle which is associated with the specified task</returns>
        public ITimeout NewTimeout(ITimerTask task, TimeSpan span)
        {
            if (task == null)
            {
                throw new ArgumentNullException(nameof(task));
            }

            if (_cancellationTokenSource != default && _cancellationTokenSource.Token.IsCancellationRequested)
            {
                throw new InvalidOperationException("cannot be started once stopped");
            }

            var pendingTimeoutsCount = _pendingTimeouts.IncrementAndGet();

            if (_maxPendingTimeouts > 0 && pendingTimeoutsCount > _maxPendingTimeouts)
            {
                _pendingTimeouts.DecrementAndGet();
                throw new InvalidOperationException(
                          $"Number of pending timeouts ({pendingTimeoutsCount}) is greater than or equal to maximum allowed pending  timeouts ({_maxPendingTimeouts})");
            }

            Start();

            // Add the timeout to the timeout queue which will be processed on the next tick.
            // During processing all the queued HashedWheelTimeouts will be added to the correct HashedWheelBucket.
            var deadline = DateTimeHelper.TotalMilliseconds + (long)span.TotalMilliseconds - StartTime;

            // Guard against overflow.
            if (span.Milliseconds > 0 && deadline < 0)
            {
                deadline = long.MaxValue;
            }

            var timeout = new HashedWheelTimeout(this, task, deadline);

            _timeouts.Enqueue(timeout);
            return(timeout);
        }
Ejemplo n.º 8
0
        /// <summary>
        /// Schedules the specified TimerTask for one-time execution after the specified delay.
        /// </summary>
        /// <param name="task"></param>
        /// <param name="span"></param>
        /// <returns>a handle which is associated with the specified task</returns>
        public Timeout NewTimeout(TimerTask task, TimeSpan span)
        {
            if (task == null)
            {
                throw new ArgumentNullException(nameof(task));
            }

            if (_workerState == WORKER_STATE_SHUTDOWN)
            {
                return(null);
            }

            long pendingTimeoutsCount = Interlocked.Increment(ref _pendingTimeouts);

            if (_maxPendingTimeouts > 0 && pendingTimeoutsCount > _maxPendingTimeouts)
            {
                Interlocked.Decrement(ref _pendingTimeouts);
                throw new InvalidOperationException($"Number of pending timeouts ({pendingTimeoutsCount}) is greater than or equal to maximum allowed pending  timeouts ({_maxPendingTimeouts})");
            }

            Start();

            // Add the timeout to the timeout queue which will be processed on the next tick.
            // During processing all the queued HashedWheelTimeouts will be added to the correct HashedWheelBucket.
            long deadline = GetCurrentMs() + (long)span.TotalMilliseconds - _startTime;

            // Guard against overflow.
            if (span.TotalMilliseconds > 0 && deadline < 0)
            {
                deadline = long.MaxValue;
            }
            HashedWheelTimeout timeout = new HashedWheelTimeout(this, task, deadline);

            _timeouts.Enqueue(timeout);
            return(timeout);
        }
 internal void EnqueueCanceledTimeout(HashedWheelTimeout timeout)
 {
     _cancelledTimeouts.Enqueue(timeout);
 }