public Task RegisterAsync(Action asyncCallback) { if (asyncCallback == null) { throw new ArgumentNullException(nameof(asyncCallback)); } CallBackRequest request = new CallBackRequest(asyncCallback, TickGeneratorRequest.Add); if (Status == TickGeneratorStatus.Disposed) { return(request.TrySetDisposed().Task); } if (Status == TickGeneratorStatus.Disposing) { return(request.TrySetCanceled().Task); } using (Lock.Enter()) { NullSafeSequencer.PointArg(SeqPointTypeUC.Notify, TickGeneratorSequencer.RegisterStatus, Status); NullSafeSequencer.PointArg(SeqPointTypeUC.Notify, TickGeneratorSequencer.RegisterActiveProcessing, ActiveProcessing); if (Status == TickGeneratorStatus.Disposed) { return(request.TrySetDisposed().Task); } if (Status == TickGeneratorStatus.Disposing) { return(request.TrySetCanceled().Task); } Requests.Enqueue(request); if (ActiveProcessing) { return(request.Task); } } if (Processing(processActions: false) == ProcessingResult.Processed) { return(request.Task); } using (Lock.Enter()) { NullSafeSequencer.PointArg(SeqPointTypeUC.Notify, TickGeneratorSequencer.RegisterEnd, Status); if (Status == TickGeneratorStatus.Disposed) { return(request.TrySetDisposed().Task); } TryUpdateTimer(activate: true); return(request.Task); } }
protected virtual ProcessingResult Processing(bool processActions) { using (var entry = ConcurrencyLimiter.TryEnter()) { ProcessingResult result = entry.HasEntry ? ProcessingResult.Processed : ProcessingResult.ExclusiveSkip; NullSafeSequencer.PointArg(SeqPointTypeUC.Notify, TimerProcessorSequencer.Processing, result); if (result == ProcessingResult.Processed) { ExclusiveProcessing(processActions); } return(result); } }
public AsyncTimerProcessorResult <TArg> RegisterAsync <TArg>(TimeSpan delay) { TimerProcessorCallBackRequest request = TimerProcessorCallBackRequest.Add <TArg>(RealTimeSource.GetUtcNow(), delay); if (Status == TimerProcessorStatus.Disposed) { return(request.TrySetDisposed().GetAsyncResult <TArg>()); } if (Status == TimerProcessorStatus.Disposing) { return(request.TrySetCanceled().GetAsyncResult <TArg>()); } using (Lock.Enter()) { NullSafeSequencer.PointArg(SeqPointTypeUC.Notify, TimerProcessorSequencer.RegisterStatus, Status); NullSafeSequencer.PointArg(SeqPointTypeUC.Notify, TimerProcessorSequencer.RegisterActiveProcessing, ActiveProcessing); if (Status == TimerProcessorStatus.Disposed) { return(request.TrySetDisposed().GetAsyncResult <TArg>()); } if (Status == TimerProcessorStatus.Disposing) { return(request.TrySetCanceled().GetAsyncResult <TArg>()); } Requests.Enqueue(request); if (ActiveProcessing) { return(request.GetAsyncResult <TArg>()); } } if (Processing(processActions: false) == ProcessingResult.Processed) { return(request.GetAsyncResult <TArg>()); } using (Lock.Enter()) { NullSafeSequencer.PointArg(SeqPointTypeUC.Notify, TimerProcessorSequencer.RegisterEnd, Status); if (Status == TimerProcessorStatus.Disposed) { return(request.TrySetDisposed().GetAsyncResult <TArg>()); } TryUpdateTimer(activate: true); return(request.GetAsyncResult <TArg>()); } }
public AsyncTimerProcessorResult <TArg> UnRegisterAsync <TArg>(TaskCompletionSource <TArg> tcs) { if (tcs == null) { throw new ArgumentNullException(nameof(tcs)); } TimerProcessorCallBackRequest request = TimerProcessorCallBackRequest.Remove(tcs); if (Status == TimerProcessorStatus.Disposed) { return(request.TrySetDisposed().GetAsyncResult <TArg>()); } using (Lock.Enter()) { if (Status == TimerProcessorStatus.Disposed) { return(request.TrySetDisposed().GetAsyncResult <TArg>()); } NullSafeSequencer.PointArg(SeqPointTypeUC.Notify, TimerProcessorSequencer.UnRegisterStatus, Status); NullSafeSequencer.PointArg(SeqPointTypeUC.Notify, TimerProcessorSequencer.UnRegisterActiveProcessing, ActiveProcessing); Requests.Enqueue(request); if (ActiveProcessing) { return(request.GetAsyncResult <TArg>()); } } if (Processing(processActions: false) == ProcessingResult.Processed) { return(request.GetAsyncResult <TArg>()); } using (Lock.Enter()) { NullSafeSequencer.PointArg(SeqPointTypeUC.Notify, TimerProcessorSequencer.UnRegisterEnd, Status); if (Status == TimerProcessorStatus.Disposed) { return(request.TrySetDisposed().GetAsyncResult <TArg>()); } TryUpdateTimer(activate: true); return(request.GetAsyncResult <TArg>()); } }
protected virtual TimerProcessorTimerStatus TryUpdateTimer(bool activate) { NullSafeSequencer.PointArg(SeqPointTypeUC.Match, TimerProcessorSequencer.TryUpdateTimerBegin, IsActive ? TimerProcessorTimerStatus.IsActive : TimerProcessorTimerStatus.None); TimerProcessorTimerStatus result = TimerProcessorTimerStatus.None; result |= activate ? TimerProcessorTimerStatus.Activate : result; if (activate && !IsActive && Period.HasValue) { Ticker.RegisterAsync(CallBackProcessing); IsActive = true; result |= TimerProcessorTimerStatus.Changed; } if (!activate && IsActive) { Ticker.UnRegisterAsync(CallBackProcessing); IsActive = false; result |= TimerProcessorTimerStatus.Changed; } result |= IsActive ? TimerProcessorTimerStatus.IsActive : result; NullSafeSequencer.PointArg(SeqPointTypeUC.Match, TimerProcessorSequencer.TryUpdateTimerEnd, result); return(result); }
protected virtual TickGeneratorTimerStatus TryUpdateTimer(bool activate) { NullSafeSequencer.PointArg(SeqPointTypeUC.Match, TickGeneratorSequencer.TryUpdateTimerBegin, IsActive ? TickGeneratorTimerStatus.IsActive : TickGeneratorTimerStatus.None); TickGeneratorTimerStatus result = TickGeneratorTimerStatus.None; result |= activate ? TickGeneratorTimerStatus.Activate : result; if (activate && !IsActive && Period.HasValue) { Timer.Change(Period.Value, Period.Value); IsActive = true; result |= TickGeneratorTimerStatus.Changed; } if (!activate && IsActive) { Timer.Change(Timeout.Infinite, Timeout.Infinite); IsActive = false; result |= TickGeneratorTimerStatus.Changed; } result |= IsActive ? TickGeneratorTimerStatus.IsActive : result; NullSafeSequencer.PointArg(SeqPointTypeUC.Match, TickGeneratorSequencer.TryUpdateTimerEnd, result); return(result); }
public bool TryExpire(DateTime now) { for (int i = 0; i < SortedList.Count; ++i) { TimerProcessorItem item = SortedList.Values[i]; if (now < item.Expiry) { break; } Remove.Push(i); NullSafeSequencer.PointArg(SeqPointTypeUC.Match, OrderedExpiryItemsSequencer.TryExpireBegin, item); item.TryExpire(); NullSafeSequencer.PointArg(SeqPointTypeUC.Match, OrderedExpiryItemsSequencer.TryExpireEnd, item); } bool somethingExpired = Remove.Count > 0; while (Remove.Count > 0) { SortedList.RemoveAt(Remove.Pop()); } return(somethingExpired); }
public void Dispose() { if (Status >= TimerProcessorStatus.Disposing) { return; } using (Lock.Enter()) { if (Status >= TimerProcessorStatus.Disposing) { return; } Status = TimerProcessorStatus.Disposing; NullSafeSequencer.PointArg(SeqPointTypeUC.Notify, TimerProcessorSequencer.DisposeStatus, Status); NullSafeSequencer.PointArg(SeqPointTypeUC.Notify, TimerProcessorSequencer.DisposeActiveProcessing, ActiveProcessing); if (ActiveProcessing) { return; } } if (Processing(processActions: false) == ProcessingResult.Processed) { return; } using (Lock.Enter()) { NullSafeSequencer.PointArg(SeqPointTypeUC.Notify, TimerProcessorSequencer.DisposedEnd, Status); if (Status == TimerProcessorStatus.Disposed) { return; } TryUpdateTimer(activate: true); } }
protected virtual void ExclusiveProcessing(bool processActions) { NullSafeSequencer.PointArg(SeqPointTypeUC.Match, TimerProcessorSequencer.ExclusiveProcessing, processActions); TimerProcessorStatus lastStatus; using (Lock.Enter()) { ActiveProcessing = true; NullSafeSequencer.PointArg(SeqPointTypeUC.Match, TimerProcessorSequencer.BeginActiveProcessing, Status); } while (true) { using (Lock.Enter()) { lastStatus = Status; while (Requests.Count > 0 && WorkingRequests.Count < MaxActiveRequests) { WorkingRequests.Enqueue(Requests.Dequeue()); } if (Requests.Count <= 0 && WorkingRequests.Count <= 0) { break; } } TimerProcessorCallBackRequest.Processing(lastStatus, WorkingRequests, ExpiryItems); } bool processing = processActions && lastStatus != TimerProcessorStatus.Disposed && ExpiryItems.Any(); NullSafeSequencer.PointArg(SeqPointTypeUC.Match, TimerProcessorSequencer.ActionsProcessing, processing); if (processing) { NullSafeSequencer.PointArg(SeqPointTypeUC.Notify, TimerProcessorSequencer.ActionsProcessingCount, ExpiryItems.Count); ExpiryItems.TryExpire(RealTimeSource.GetUtcNow()); } while (true) { using (Lock.Enter()) { lastStatus = Status; while (Requests.Count > 0 && WorkingRequests.Count < MaxActiveRequests) { WorkingRequests.Enqueue(Requests.Dequeue()); } if (Requests.Count <= 0 && WorkingRequests.Count <= 0) { break; } } TimerProcessorCallBackRequest.Processing(lastStatus, WorkingRequests, ExpiryItems); } using (Lock.Enter()) { ActiveProcessing = false; TimerProcessorCallBackRequest.Processing(Status, Requests, ExpiryItems); if (Status == TimerProcessorStatus.Operating) { bool activate = false; activate |= ExpiryItems.Count > 0; activate |= Requests.Count > 0; TryUpdateTimer(activate); } else { TryUpdateTimer(activate: false); ExpiryItems.CancelAllAndClear(); Status = TimerProcessorStatus.Disposed; Ticker.Dispose(); DisposedTCS.TrySetResult(null); } NullSafeSequencer.PointArg(SeqPointTypeUC.Match, TimerProcessorSequencer.EndActiveProcessing, Status); } }
protected virtual void ExclusiveProcessing(bool processActions) { NullSafeSequencer.PointArg(SeqPointTypeUC.Match, TickGeneratorSequencer.ExclusiveProcessing, processActions); TickGeneratorStatus lastStatus; using (Lock.Enter()) { ActiveProcessing = true; NullSafeSequencer.PointArg(SeqPointTypeUC.Match, TickGeneratorSequencer.BeginActiveProcessing, Status); } while (true) { using (Lock.Enter()) { lastStatus = Status; while (Requests.Count > 0 && WorkingRequests.Count < MaxActiveRequests) { WorkingRequests.Enqueue(Requests.Dequeue()); } if (Requests.Count <= 0 && WorkingRequests.Count <= 0) { break; } } CallBackRequest.Processing(lastStatus, WorkingRequests, Actions); } bool processing = processActions && lastStatus != TickGeneratorStatus.Disposed && Actions.Count > 0; NullSafeSequencer.PointArg(SeqPointTypeUC.Match, TickGeneratorSequencer.ActionsProcessing, processing); if (processing) { NullSafeSequencer.PointArg(SeqPointTypeUC.Notify, TickGeneratorSequencer.ActionsProcessingCount, Actions.Count); foreach (Action action in Actions) { action(); } } while (true) { using (Lock.Enter()) { lastStatus = Status; while (Requests.Count > 0 && WorkingRequests.Count < MaxActiveRequests) { WorkingRequests.Enqueue(Requests.Dequeue()); } if (Requests.Count <= 0 && WorkingRequests.Count <= 0) { break; } } CallBackRequest.Processing(lastStatus, WorkingRequests, Actions); } using (Lock.Enter()) { ActiveProcessing = false; CallBackRequest.Processing(lastStatus, Requests, Actions); if (Status == TickGeneratorStatus.Operating) { bool activate = false; activate |= Actions.Count > 0; activate |= Requests.Count > 0; TryUpdateTimer(activate); } else { TryUpdateTimer(activate: false); Period = null; Actions.Clear(); Status = TickGeneratorStatus.Disposed; DisposedTCS.TrySetResult(null); } NullSafeSequencer.PointArg(SeqPointTypeUC.Match, TickGeneratorSequencer.EndActiveProcessing, Status); } }