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); }
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); }
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(); }); }