public virtual async Task <TOut> InvokeAndStrip(TIn input, IComputed?usedBy, ComputeContext?context, CancellationToken cancellationToken = default) { context ??= ComputeContext.Current; Result <TOut> output; // Read-Lock-RetryRead-Compute-Store pattern var result = GetExisting(input); if (result.TryUseExisting(context, usedBy)) { return(result.Strip(context)); } using var @lock = await Locks.Lock(input, cancellationToken).ConfigureAwait(false); result = GetExisting(input); if (result.TryUseExisting(context, usedBy)) { return(result.Strip(context)); } result = await Compute(input, result, cancellationToken).ConfigureAwait(false); output = result.Output; // It can't be gone here b/c KeepAlive isn't called yet result.UseNew(context, usedBy); return(output.Value); }
public virtual async Task <IComputed <TOut> > Invoke(TIn input, IComputed?usedBy, ComputeContext?context, CancellationToken cancellationToken = default) { context ??= ComputeContext.Current; // Read-Lock-RetryRead-Compute-Store pattern var result = GetExisting(input); if (result.TryUseExisting(context, usedBy)) { return(result !); } using var @lock = await Locks.Lock(input, cancellationToken).ConfigureAwait(false); result = GetExisting(input); if (result.TryUseExisting(context, usedBy)) { return(result !); } result = await Compute(input, result, cancellationToken).ConfigureAwait(false); result.UseNew(context, usedBy); return(result); }
public override async Task <T> InvokeAndStrip( ComputeMethodInput input, IComputed?usedBy, ComputeContext?context, CancellationToken cancellationToken = default) { context ??= ComputeContext.Current; ResultBox <T>?output; // Read-Lock-RetryRead-Compute-Store pattern var computed = TryGetExisting(input); if (computed != null) { output = await computed.TryUseExisting(context, usedBy, cancellationToken) .ConfigureAwait(false); if (output != null) { return(output.Value); } } using var @lock = await Locks.Lock(input, cancellationToken).ConfigureAwait(false); computed = TryGetExisting(input); if (computed != null) { output = await computed.TryUseExisting(context, usedBy, cancellationToken) .ConfigureAwait(false); if (output != null) { return(output.Value); } } computed = (IAsyncComputed <T>) await Compute(input, computed, cancellationToken) .ConfigureAwait(false); var rOutput = computed.Output; // RenewTimeouts isn't called yet, so it's ok computed.UseNew(context, usedBy); return(rOutput !.Value); }