Esempio n. 1
0
        internal static bool TryUseExisting <T>(this IComputed <T>?existing, ComputeContext context, IComputed?usedBy)
        {
            var callOptions = context.CallOptions;
            var useExisting = (callOptions & CallOptions.TryGetExisting) != 0;

            if (existing == null)
            {
                return(useExisting);
            }
            if (!(useExisting || existing.IsConsistent()))
            {
                return(false);
            }

            context.TryCapture(existing);
            var invalidate = (callOptions & CallOptions.Invalidate) == CallOptions.Invalidate;

            if (invalidate)
            {
                existing.Invalidate();
                return(true);
            }
            if (!useExisting)
            {
                ((IComputedImpl?)usedBy)?.AddUsed((IComputedImpl)existing !);
            }
            ((IComputedImpl?)existing)?.RenewTimeouts();
            return(true);
        }
Esempio n. 2
0
        internal static bool TryUseExisting <T>(this IComputed <T>?existing, ComputeContext context, IComputed?usedBy)
        {
            var callOptions = context.CallOptions;
            var useExisting = (callOptions & CallOptions.TryGetExisting) != 0;

            if (existing == null)
            {
                return(useExisting);
            }
            useExisting |= existing.IsConsistent();
            if (!useExisting)
            {
                return(false);
            }

            if ((callOptions & CallOptions.Capture) != 0)
            {
                Interlocked.Exchange(ref context.CapturedComputed, existing);
            }
            if ((callOptions & CallOptions.Invalidate) == CallOptions.Invalidate)
            {
                existing.Invalidate();
                return(true);
            }
            ((IComputedImpl?)usedBy)?.AddUsed((IComputedImpl)existing !);
            ((IComputedImpl?)existing)?.RenewTimeouts();
            return(true);
        }
Esempio n. 3
0
        public static void Invalidate(this IComputed computed, TimeSpan delay, bool?usePreciseTimer = null)
        {
            if (delay <= TimeSpan.Zero)
            {
                computed.Invalidate();
                return;
            }

            var bPrecise = usePreciseTimer ?? delay <= TimeSpan.FromSeconds(1);

            if (!bPrecise)
            {
                Timeouts.Invalidate.AddOrUpdateToEarlier(computed, Timeouts.Clock.Now + delay);
                computed.Invalidated += c => Timeouts.Invalidate.Remove(c);
                return;
            }

            var cts = new CancellationTokenSource(delay);

            computed.Invalidated += _ => {
                try {
                    if (!cts.IsCancellationRequested)
                    {
                        cts.Cancel(true);
                    }
                } catch {
                    // Intended: this method should never throw any exceptions
                }
            };
            cts.Token.Register(() => {
                // No need to schedule this via Task.Run, since this code is
                // either invoked from Invalidate method (via Invalidated handler),
                // so Invalidate() call will do nothing & return immediately,
                // or it's invoked via one of timer threads, i.e. where it's
                // totally fine to invoke Invalidate directly as well.
                computed.Invalidate();
                cts.Dispose();
            });
        }