예제 #1
0
        // Initializes the the precise timing mechanism
        private static void InitializePreciseTime()
        {
            // We just use the recommended synchronization period for general purpose use
            const int synchronizationPeriod = 10;

            // Create a new precise time class
            s_preciseTime = new PreciseTime(synchronizationPeriod);

            // We setup a lightweight timer that will make sure precise time mechanism gets
            // called regularly, in case user doesn't, so it can maintain synchronization
            s_synchronizer          = new Timer(synchronizationPeriod * 1000.0D);
            s_synchronizer.Elapsed += s_synchronizer_Elapsed;
            s_synchronizer.Start();
        }
예제 #2
0
        internal long RunScheduledTasks()
        {
            var time = PreciseTime.NanoTime();

            while (true)
            {
                IRunnable task = PollScheduledTask(time);
                if (task is null)
                {
                    return(NextScheduledTaskNanos());
                }
                task.Run();
            }
        }
예제 #3
0
        private void TestScheduleLaggyTaskAtFixedRate(IEventLoop loopA)
        {
            var timestamps         = new BlockingCollection <long>();
            int expectedTimeStamps = 5;
            var allTimeStampsLatch = new CountdownEvent(expectedTimeStamps);
            var f = loopA.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)));
                }
                previousTimestamp = t;
                i++;
            }
        }
예제 #4
0
 internal void ProcessVoteConfirmation(Connection sender, int term)
 {
     serialLock.AssertIsLockedByMe();
     LogMinorEvent("Processing vote confirmation for term " + term + " from " + sender);
     if (state == State.Candidate && term == currentTerm)
     {
         nextActionAt = GetElectionTimeout();
         numVotes++;
         CheckElectionMajority();
     }
     else
     {
         LogMinorEvent("Confirmation rejected: " + state + ", t" + term);
     }
 }
예제 #5
0
        public void TestScheduling()
        {
            var  ch     = new EmbeddedChannel(new ChannelHandlerAdapter());
            var  latch  = new CountdownEvent(2);
            Task future = ch.EventLoop.ScheduleAsync(() => latch.Signal(), TimeSpan.FromSeconds(1));

            future.ContinueWith(t => latch.Signal());
            var next = ch.RunScheduledPendingTasks();

            Assert.True(next > PreciseTime.Zero);
            // Sleep for the nanoseconds but also give extra 50ms as the clock my not be very precise and so fail the test
            // otherwise.
            Thread.Sleep(PreciseTime.ToTimeSpan(next) + TimeSpan.FromMilliseconds(50));
            Assert.Equal(PreciseTime.MinusOne, ch.RunScheduledPendingTasks());
            latch.Wait();
        }
예제 #6
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);
        }
        public override Task ScheduleAsync(Action <object> action, object state, TimeSpan delay, CancellationToken cancellationToken)
        {
            if (cancellationToken.IsCancellationRequested)
            {
                return(TaskUtil.Cancelled);
            }

            if (!cancellationToken.CanBeCanceled)
            {
                return(Schedule(action, state, delay).Completion);
            }

            if (action is null)
            {
                return(ThrowHelper.FromArgumentNullException(ExceptionArgument.action));
            }

            return(Schedule(new StateActionScheduledAsyncTask(this, action, state, PreciseTime.DeadlineNanos(delay), cancellationToken)).Completion);
        }
예제 #8
0
 private void CommitTo(int newCommitCount)
 {
     serialLock.AssertIsLockedByMe();
     try
     {
         if (commitCount < newCommitCount)
         {
             lastCommit = DateTime.Now;
             LogMinorEvent("Committing " + commitCount + ".." + newCommitCount + ", history length " + log.Count);
             for (int i = commitCount; i < newCommitCount; i++)
             {
                 PrivateEntry e = log[i];
                 if (e == null)
                 {
                     LogMinorEvent("Skipping removed entry at #" + i);
                 }
                 else
                 {
                     if (DebugState != null)
                     {
                         DebugState.SignalExecution(i, e.Entry.Term, this);
                     }
                     if (!e.WasExecuted)
                     {
                         commitCount = Math.Max(commitCount, i + 1);
                         LogMinorEvent("Executing " + e.Entry);
                         e.Execute(this);
                         committed.TryRemove(e.Entry.CommitID);
                     }
                 }
             }
             //Debug.Assert(commitCount == newCommitCount);
             if (IsLeader)
             {
                 Broadcast(new AppendEntries(this));
                 nextActionAt = NextHeartbeat;
             }
         }
     }
     catch (Exception ex)
     {
     }
 }
예제 #9
0
 internal void Yield()
 {
     serialLock.AssertIsLockedByMe();
     LogEvent("Yielding...");
     state    = State.Follower;
     leader   = null;
     votedFor = null;
     //votedInTerm = -1;
     nextActionAt = GetElectionTimeout();
     if (cfgChange != null)
     {
         Join(cfgChange.NewCFG);
         if (cfgChange != null)
         {
             throw new IntegrityViolation("Consensus: New CFG should have been unset by Join()");
         }
     }
     OnConsensusChange(Status.NotEstablished, null);
 }
        /// <summary>
        /// Return <c>true</c> if at least one scheduled task was executed.
        /// </summary>
        private bool ExecuteExpiredScheduledTasks()
        {
            if (_scheduledTaskQueue.IsEmpty)
            {
                return(false);
            }

            var nanoTime      = PreciseTime.NanoTime();
            var scheduledTask = PollScheduledTask(nanoTime);

            if (scheduledTask is null)
            {
                return(false);
            }
            do
            {
                SafeExecute(scheduledTask);
            } while ((scheduledTask = PollScheduledTask(nanoTime)) is object);
            return(true);
        }
        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));
        }
예제 #12
0
        internal void ProcessVoteRequest(Connection sender, int term, bool upToDate)
        {
            serialLock.AssertIsLockedByMe();

            if ((/*votedFor == null ||*/ votedFor == sender || term > currentTerm) && upToDate)                 //already voted: all good.
            {
                Yield();
                //state = State.Follower;
                //leader = null;	leave old leader in place
                LogMinorEvent("Recognized vote request for term " + term + " from " + sender);
                //nextActionAt = GetElectionTimeout();
                votedFor    = sender;
                currentTerm = term;
                //currentTerm = term;


                //!!!!we voted: we cannot accept any other appendentries from our last leader!!!!



                try
                {
                    sender.Dispatch(new VoteConfirm(currentTerm));
                }
                catch
                {
                    bool brk = true;
                }
            }
            else
            {
                LogMinorEvent("Rejected vote request for term " + term + " (at term " + currentTerm + ", upToDate=" + upToDate + ") from " + sender);
                if (term > currentTerm)
                {
                    bool now = state == State.Candidate && !upToDate;                           //preemt
                    currentTerm = term;
                    Yield();
                    nextActionAt = now ? PreciseTime.Now : GetElectionTimeout();
                }
            }
        }
예제 #13
0
        public void ScheduleTaskAtFixedRate()
        {
            var timestamps         = new BlockingCollection <long>();
            int expectedTimeStamps = 5;
            var allTimeStampsLatch = new CountdownEvent(expectedTimeStamps);
            var f = this.eventLoop.ScheduleAtFixedRate(() =>
            {
                timestamps.Add(Stopwatch.GetTimestamp());
                try
                {
                    Thread.Sleep(50);
                }
                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 without a lag.
            long?firstTimestamp = null;
            int  cnt            = 0;

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

                long timepoint = t - firstTimestamp.Value;
                Assert.True(timepoint >= PreciseTime.ToDelayNanos(TimeSpan.FromMilliseconds(100 * cnt + 80)));
                Assert.True(timepoint <= PreciseTime.ToDelayNanos(TimeSpan.FromMilliseconds(100 * (cnt + 1) + 20)));

                cnt++;
            }
        }
예제 #14
0
        private bool FetchFromScheduledTaskQueue()
        {
            if (_scheduledTaskQueue.IsEmpty)
            {
                return(true);
            }

            var nanoTime = PreciseTime.NanoTime();
            IScheduledRunnable scheduledTask = PollScheduledTask(nanoTime);

            while (scheduledTask is object)
            {
                if (!_taskQueue.TryEnqueue(scheduledTask))
                {
                    // No space left in the task queue add it back to the scheduledTaskQueue so we pick it up again.
                    _ = _scheduledTaskQueue.TryEnqueue(scheduledTask);
                    return(false);
                }
                scheduledTask = PollScheduledTask(nanoTime);
            }
            return(true);
        }
예제 #15
0
        protected override void AfterRunningAllTasks()
        {
            const long MaxDelayMilliseconds = int.MaxValue - 1;

#if DEBUG
            base.AfterRunningAllTasks();
#endif

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

            var nextTimeout = InfiniteBreakoutTime;
            if (HasTasks)
            {
                nextTimeout = DefaultBreakoutTime;
            }
            else if (TryPeekScheduledTask(out IScheduledRunnable nextScheduledTask))
            {
                long delayNanos = nextScheduledTask.DelayNanos;
                if ((ulong)delayNanos > 0UL) // delayNanos 为非负值
                {
                    var timeout = PreciseTime.ToMilliseconds(delayNanos);
                    nextTimeout = Math.Min(timeout, MaxDelayMilliseconds);
                }
                else
                {
                    nextTimeout = MinimumBreakoutTime;
                }
            }

            if ((ulong)nextTimeout > 0UL) // nextTimeout 为非负值
            {
                _ = _timerHandle.Start(nextTimeout, 0);
            }
        }
예제 #16
0
        public void TestGracefulShutdownQuietPeriod()
        {
            _loopA.ShutdownGracefullyAsync(TimeSpan.FromSeconds(1), TimeSpan.FromDays(1));
            // Keep Scheduling tasks for another 2 seconds.
            for (int i = 0; i < 20; i++)
            {
                Thread.Sleep(100);
                _loopA.Execute(NOOP.Instance);
            }

            long startTime = PreciseTime.NanoTime();

            Assert.True(_loopA.IsShuttingDown);
            Assert.False(_loopA.IsShutdown);

            while (!_loopA.IsTerminated)
            {
                _loopA.WaitTermination(TimeSpan.FromDays(1));
            }

            Assert.True(PreciseTime.NanoTime() - startTime >= PreciseTime.ToDelayNanos(TimeSpan.FromSeconds(1)));
        }
예제 #17
0
        protected bool FetchFromScheduledTaskQueue()
        {
            if (ScheduledTaskQueue.IsEmpty)
            {
                return(true);
            }

            var nanoTime      = PreciseTime.NanoTime();
            var scheduledTask = PollScheduledTask(nanoTime);
            var taskQueue     = _taskQueue;

            while (scheduledTask is object)
            {
                if (!taskQueue.TryEnqueue(scheduledTask))
                {
                    // No space left in the task queue add it back to the scheduledTaskQueue so we pick it up again.
                    _ = ScheduledTaskQueue.TryEnqueue(scheduledTask);
                    return(false);
                }
                scheduledTask = PollScheduledTask(nanoTime);
            }
            return(true);
        }
        public override Task ScheduleWithFixedDelayAsync(Action <object> action, object state, TimeSpan initialDelay, TimeSpan delay, CancellationToken cancellationToken)
        {
            if (cancellationToken.IsCancellationRequested)
            {
                return(TaskUtil.Cancelled);
            }

            if (!cancellationToken.CanBeCanceled)
            {
                return(ScheduleWithFixedDelay(action, state, initialDelay, delay).Completion);
            }

            if (action is null)
            {
                return(ThrowHelper.FromArgumentNullException(ExceptionArgument.action));
            }
            if (delay <= TimeSpan.Zero)
            {
                return(ThrowHelper.FromArgumentException_DelayMustBeGreaterThanZero());
            }

            return(Schedule(new StateActionScheduledAsyncTask(this, action, state, PreciseTime.DeadlineNanos(initialDelay), -PreciseTime.ToDelayNanos(delay), cancellationToken)).Completion);
        }
        public override Task ScheduleAtFixedRateAsync(Action action, TimeSpan initialDelay, TimeSpan period, CancellationToken cancellationToken)
        {
            if (cancellationToken.IsCancellationRequested)
            {
                return(TaskUtil.Cancelled);
            }

            if (!cancellationToken.CanBeCanceled)
            {
                return(ScheduleAtFixedRate(action, initialDelay, period).Completion);
            }

            if (action is null)
            {
                return(ThrowHelper.FromArgumentNullException(ExceptionArgument.action));
            }
            if (period <= TimeSpan.Zero)
            {
                return(ThrowHelper.FromArgumentException_PeriodMustBeGreaterThanZero());
            }

            return(Schedule(new ActionScheduledAsyncTask(this, action, PreciseTime.DeadlineNanos(initialDelay), PreciseTime.ToDelayNanos(period), cancellationToken)).Completion);
        }
예제 #20
0
        public void GracefulShutdownQuietPeriod()
        {
            Task task = this.eventLoop.ShutdownGracefullyAsync(TimeSpan.FromSeconds(1), TimeSpan.MaxValue);

            // Keep Scheduling tasks for another 2 seconds.
            for (int i = 0; i < 20; i++)
            {
                Thread.Sleep(100);
                this.eventLoop.Execute(new NoOp());
            }

            long startTime = PreciseTime.NanoTime();

            Assert.True(this.eventLoop.IsShuttingDown);
            Assert.False(this.eventLoop.IsShutdown);
            Assert.True(task.Wait(DefaultTimeout), "Loop shutdown timed out");

            Assert.True(this.eventLoop.IsShuttingDown);
            Assert.True(this.eventLoop.IsShutdown);

            long duration = (long)PreciseTime.ToTimeSpan(PreciseTime.NanoTime() - startTime).TotalMilliseconds;

            Assert.True(duration >= 1000, $"Expecting shutdown quite period >= 1000 milliseconds, but was {duration}");
        }
예제 #21
0
        public void ScheduleTaskWithFixedDelay()
        {
            var timestamps         = new BlockingCollection <long>();
            int expectedTimeStamps = 3;
            var allTimeStampsLatch = new CountdownEvent(expectedTimeStamps);
            var f = this.eventLoop.ScheduleWithFixedDelay(() =>
            {
                timestamps.Add(Stopwatch.GetTimestamp());
                try
                {
                    Thread.Sleep(51);
                }
                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 without a lag.
            long?previousTimestamp = null;

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

                Assert.True(t - previousTimestamp.Value >= PreciseTime.ToDelayNanos(TimeSpan.FromMilliseconds(150)));
                previousTimestamp = t;
            }
        }
 protected static long DeadlineToDelayNanos(long deadlineNanos) => PreciseTime.DeadlineToDelayNanos(deadlineNanos);
 protected static long NanoTime() => PreciseTime.NanoTime();
 protected virtual long GetTimeFromStart()
 {
     return(PreciseTime.NanoTime());
 }
        public override IScheduledTask ScheduleWithFixedDelay(Action <object, object> action, object context, object state, TimeSpan initialDelay, TimeSpan delay)
        {
            if (action is null)
            {
                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.action);
            }
            if (delay <= TimeSpan.Zero)
            {
                ThrowHelper.ThrowArgumentException_DelayMustBeGreaterThanZero();
            }

            return(Schedule(new StateActionWithContextScheduledTask(this, action, context, state, PreciseTime.DeadlineNanos(initialDelay), -PreciseTime.ToDelayNanos(delay))));
        }
        public override IScheduledTask ScheduleWithFixedDelay(IRunnable action, TimeSpan initialDelay, TimeSpan delay)
        {
            if (action is null)
            {
                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.action);
            }
            if (delay <= TimeSpan.Zero)
            {
                ThrowHelper.ThrowArgumentException_DelayMustBeGreaterThanZero();
            }

            return(Schedule(new RunnableScheduledTask(this, action, PreciseTime.DeadlineNanos(initialDelay), -PreciseTime.ToDelayNanos(delay))));
        }
        public override IScheduledTask ScheduleAtFixedRate(Action <object> action, object state, TimeSpan initialDelay, TimeSpan period)
        {
            if (action is null)
            {
                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.action);
            }
            if (period <= TimeSpan.Zero)
            {
                ThrowHelper.ThrowArgumentException_PeriodMustBeGreaterThanZero();
            }

            return(Schedule(new StateActionScheduledTask(this, action, state, PreciseTime.DeadlineNanos(initialDelay), PreciseTime.ToDelayNanos(period))));
        }
        public override IScheduledTask Schedule(Action <object, object> action, object context, object state, TimeSpan delay)
        {
            if (action is null)
            {
                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.action);
            }

            return(Schedule(new StateActionWithContextScheduledTask(this, action, context, state, PreciseTime.DeadlineNanos(delay))));
        }
 /// <summary>
 /// Returns <c>true</c> if a scheduled task is ready for processing.
 /// </summary>
 protected bool HasScheduledTasks()
 {
     return(ScheduledTaskQueue.TryPeek(out IScheduledRunnable scheduledTask) && scheduledTask.DeadlineNanos <= PreciseTime.NanoTime());
 }
 protected virtual long ToPreciseTime(TimeSpan time)
 {
     return(PreciseTime.TicksToPreciseTicks(time.Ticks));
 }
예제 #31
0
        private static PreciseTime m_preciseTime;           // Precise time implementation.

        // Static Constructor
        static PrecisionTimer()
        {
            // Get multimedia timer capabilities
            timeGetDevCaps(ref m_capabilities, Marshal.SizeOf(m_capabilities));

            // We just use the recommended synchronization period for general purpose TVA use
            m_preciseTime = new PreciseTime(10);
        }
예제 #32
0
파일: PrecisionTimer.cs 프로젝트: rmc00/gsf
        // Initializes the the precise timing mechanism
        private static void InitializePreciseTime()
        {
            // We just use the recommended synchronization period for general purpose use
            const int synchronizationPeriod = 10;

            // Create a new precise time class
            s_preciseTime = new PreciseTime(synchronizationPeriod);

            // We setup a lightweight timer that will make sure precise time mechanism gets
            // called regularly, in case user doesn't, so it can maintain synchronization
            s_synchronizer = new Timer(synchronizationPeriod * 1000.0D);
            s_synchronizer.Elapsed += s_synchronizer_Elapsed;
            s_synchronizer.Start();
        }