Example #1
0
        protected override void AfterRunningAllTasks()
        {
            const long MaxDelayMilliseconds = int.MaxValue - 1;

#if DEBUG
            base.AfterRunningAllTasks();
#endif

            if (IsShuttingDown)
            {
                // Immediate shutdown
                WakeUp(true);
                return;
            }

            long nextTimeout = DefaultBreakoutTime;
            if (HasTasks)
            {
                _ = _timerHandle.Start(nextTimeout, 0);
            }
            else
            {
                if (ScheduledTaskQueue.TryPeek(out IScheduledRunnable nextScheduledTask))
                {
                    long delayNanos = nextScheduledTask.DelayNanos;
                    if ((ulong)delayNanos > 0UL) // delayNanos >= 0
                    {
                        var timeout = PreciseTime.ToMilliseconds(delayNanos);
                        nextTimeout = Math.Min(timeout, MaxDelayMilliseconds);
                    }
                    _ = _timerHandle.Start(nextTimeout, 0);
                }
            }
        }
Example #2
0
        public void ScheduleLaggyTaskAtFixedRate()
        {
            var timestamps         = new BlockingCollection <long>();
            int expectedTimeStamps = 5;
            var allTimeStampsLatch = new CountdownEvent(expectedTimeStamps);
            var f = this.eventLoop.ScheduleAtFixedRate(() =>
            {
                var empty = timestamps.Count == 0;
                timestamps.Add(Stopwatch.GetTimestamp());
                if (empty)
                {
                    try
                    {
                        Thread.Sleep(401);
                    }
                    catch { }
                }
                allTimeStampsLatch.Signal();
            }, TimeSpan.FromMilliseconds(100), TimeSpan.FromMilliseconds(100));

            Assert.True(allTimeStampsLatch.Wait(TimeSpan.FromMinutes(1)));
            Assert.True(f.Cancel());
            Thread.Sleep(300);
            Assert.Equal(expectedTimeStamps, timestamps.Count);

            // Check if the task was run with lag.
            int  i = 0;
            long?previousTimestamp = null;

            foreach (long t in timestamps)
            {
                if (previousTimestamp == null)
                {
                    previousTimestamp = t;
                    continue;
                }

                long diff = t - previousTimestamp.Value;
                if (i == 0)
                {
                    Assert.True(diff >= PreciseTime.ToDelayNanos(TimeSpan.FromMilliseconds(400)));
                }
                else
                {
                    //Assert.True(diff <= PreciseTime.ToDelayNanos(TimeSpan.FromMilliseconds(10 + 2)));
                    var diffMs = PreciseTime.ToMilliseconds(diff);
                    Assert.True(diffMs <= 10 + 40); // libuv 多加 40,确保测试通过
                }
                previousTimestamp = t;
                i++;
            }
        }
Example #3
0
        protected sealed override IRunnable PollTask()
        {
            const long MaxDelayMilliseconds = int.MaxValue - 1;

            Debug.Assert(InEventLoop);

            var taskQueue = _taskQueue;
            var task      = PollTaskFrom(taskQueue);

            if (task is object)
            {
                return(task);
            }
#if DEBUG
            if (_tailTasks.IsEmpty)
            {
                _emptyEvent.Reset();
            }
#else
            _emptyEvent.Reset();
#endif
            task = PollTaskFrom(taskQueue);
            if (task is object || IsShuttingDown) // revisit queue as producer might have put a task in meanwhile
            {
                return(task);
            }

            // revisit queue as producer might have put a task in meanwhile
            if (TryPeekScheduledTask(out IScheduledRunnable nextScheduledTask))
            {
                var delayNanos = nextScheduledTask.DelayNanos;
                if ((ulong)delayNanos > 0UL) // delayNanos 为非负值
                {
                    var timeout = PreciseTime.ToMilliseconds(delayNanos);
                    _emptyEvent.Wait((int)Math.Min(timeout, MaxDelayMilliseconds));
                }
            }
            else
            {
                if (!IsShuttingDown)
                {
                    _emptyEvent.Wait();
                }
                task = PollTaskFrom(taskQueue);
            }
            return(task);
        }
        private bool TryTakeTask(long delayNanos, out IRunnable task)
        {
            const long MaxDelayMilliseconds = int.MaxValue - 1;

            if ((ulong)delayNanos > 0UL) // delayNanos 为非负值
            {
                var timeout = PreciseTime.ToMilliseconds(delayNanos);
                if (_blockingTaskQueue.TryTake(out task, (int)Math.Min(timeout, MaxDelayMilliseconds)))
                {
                    return(true);
                }
            }

            // We need to fetch the scheduled tasks now as otherwise there may be a chance that
            // scheduled tasks are never executed if there is always one task in the taskQueue.
            // This is for example true for the read task of OIO Transport
            // See https://github.com/netty/netty/issues/1614
            _ = FetchFromScheduledTaskQueue();
            return(_blockingTaskQueue.TryTake(out task, 0));
        }