Exemple #1
0
        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);
        }
Exemple #6
0
        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 CallBackProcessing()
 {
     NullSafeSequencer.Point(SeqPointTypeUC.Match, TimerProcessorSequencer.CallBackProcessing);
     Processing(processActions: true);
 }
Exemple #11
0
        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);
            }
        }