// 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(); }
internal long RunScheduledTasks() { var time = PreciseTime.NanoTime(); while (true) { IRunnable task = PollScheduledTask(time); if (task is null) { return(NextScheduledTaskNanos()); } task.Run(); } }
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++; } }
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); } }
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(); }
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); }
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) { } }
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)); }
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(); } } }
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++; } }
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); }
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); } }
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))); }
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); }
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}"); }
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)); }
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); }