/// <summary> /// Returns a promise-pipelined Proxy for a remote method invocation Task. /// </summary> /// <typeparam name="TInterface">Capability interface type</typeparam> /// <param name="task">Task returning an interface</param> /// <param name="allowNoPipeliningFallback">If this flag is 'false', the <paramref name="task"/> MUST have been returned from a remote /// method invocation on a generated Proxy interface. Since this is the prerequisite for promise pipelining to work, the method throws an /// exception if the requirement is not met (i.e. the passed some Task instance was constructed "somewhere else"). Setting this flag to 'true' /// prevents such an exception. The method falls back to a local "lazy" proxy for the given Task. It is fully usable, but does not perform /// any promise pipelining (as specified for Cap'n Proto).</param> /// <returns>A proxy for the given future.</returns> /// <exception cref="ArgumentNullException"><paramref name="task"/> is null.</exception> /// <exception cref="InvalidCapabilityInterfaceException"><typeparamref name="TInterface"/> did not qualify as capability interface.</exception> /// <exception cref="ArgumentException">The task was not returned from a remote method invocation. Promise pipelining won't work. /// Setting <paramref name="allowNoPipeliningFallback"/>> to 'true' prevents this exception. /// OR: Mismatch between generic type arguments (if capability interface is generic).</exception> /// <exception cref="InvalidOperationException">Mismatch between generic type arguments (if capability interface is generic).</exception> /// <exception cref="System.Reflection.TargetInvocationException">Problem with instatiating the Proxy (constructor threw exception).</exception> /// <exception cref="MemberAccessException">Caller does not have permission to invoke the Proxy constructor.</exception> /// <exception cref="TypeLoadException">Problem with building the Proxy type, or problem with loading some dependent class.</exception> public static TInterface Eager <TInterface>(this Task <TInterface> task, bool allowNoPipeliningFallback = false) where TInterface : class, IDisposable { var answer = TryGetAnswer(task); if (answer == null) { if (!allowNoPipeliningFallback) { throw new ArgumentException("The task was not returned from a remote method invocation. See documentation for details."); } var proxyTask = task.AsProxyTask(); if (proxyTask.ReplacementTaskIsCompletedSuccessfully()) { return(proxyTask.Result.Cast <TInterface>(true)); } else { var lazyCap = new LazyCapability(proxyTask); return((CapabilityReflection.CreateProxy <TInterface>(lazyCap) as TInterface) !); } } else { async Task <IDisposable?> AsDisposableTask() { return(await task); } return((CapabilityReflection.CreateProxy <TInterface>(answer.Access(Path_OneAndOnly, AsDisposableTask())) as TInterface) !); } }
public static TInterface PseudoEager <TInterface>(this Task <TInterface> task) where TInterface : class, IDisposable { var lazyCap = new LazyCapability(task.AsProxyTask()); return((CapabilityReflection.CreateProxy <TInterface>(lazyCap) as TInterface) !); }
public static LazyCapability CreateBrokenCap(string message) { var cap = new LazyCapability(Task.FromException <Proxy>(new RpcException(message))); cap.AddRef(); // Instance shall be persistent return(cap); }
public static LazyCapability CreateCanceledCap(CancellationToken token) { var cap = new LazyCapability(Task.FromCanceled <Proxy>(token)); cap.AddRef(); // Instance shall be persistent return(cap); }
public static TInterface PseudoEager <TInterface>(this Task <TInterface> task, [System.Runtime.CompilerServices.CallerMemberName] string memberName = "", [System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "", [System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0) where TInterface : class { var lazyCap = new LazyCapability(AwaitProxy(task)); return((CapabilityReflection.CreateProxy <TInterface>(lazyCap, memberName, sourceFilePath, sourceLineNumber) as TInterface) !); }
/// <summary> /// Returns a promise-pipelined Proxy for a remote method invocation Task. /// </summary> /// <typeparam name="TInterface">Capability interface type</typeparam> /// <param name="task">Task returning an interface</param> /// <param name="allowNoPipeliningFallback">If this flag is 'false', the <paramref name="task"/> MUST have been returned from a remote /// method invocation on a generated Proxy interface. Since this is the prerequisite for promise pipelining to work, the method throws an /// exception if the requirement is not met (i.e. the passed some Task instance was constructed "somewhere else"). Setting this flag to 'true' /// prevents such an exception. The method falls back to a local "lazy" proxy for the given Task. It is fully usable, but does not perform /// any promise pipelining (as specified for Cap'n Proto).</param> /// <returns>A proxy for the given future.</returns> /// <exception cref="ArgumentNullException"><paramref name="task"/> is null.</exception> /// <exception cref="InvalidCapabilityInterfaceException"><typeparamref name="TInterface"/> did not qualify as capability interface.</exception> /// <exception cref="ArgumentException">The task was not returned from a remote method invocation. Promise pipelining won't work. /// Setting <paramref name="allowNoPipeliningFallback"/>> to 'true' prevents this exception. /// OR: Mismatch between generic type arguments (if capability interface is generic).</exception> /// <exception cref="InvalidOperationException">Mismatch between generic type arguments (if capability interface is generic).</exception> /// <exception cref="System.Reflection.TargetInvocationException">Problem with instatiating the Proxy (constructor threw exception).</exception> /// <exception cref="MemberAccessException">Caller does not have permission to invoke the Proxy constructor.</exception> /// <exception cref="TypeLoadException">Problem with building the Proxy type, or problem with loading some dependent class.</exception> public static TInterface Eager <TInterface>(this Task <TInterface> task, bool allowNoPipeliningFallback = false) where TInterface : class { var answer = TryGetAnswer(task); if (answer == null) { if (!allowNoPipeliningFallback) { throw new ArgumentException("The task was not returned from a remote method invocation. See documentation for details."); } var lazyCap = new LazyCapability(AwaitProxy(task)); return((CapabilityReflection.CreateProxy <TInterface>(lazyCap) as TInterface) !); } else { return((CapabilityReflection.CreateProxy <TInterface>(answer.Access(Path_OneAndOnly)) as TInterface) !); } }
public void Break(string message) { bool release = false; lock (_reentrancyBlocker) { #if false _resolvedCap.SetException(new RpcException(message)); #else _resolvedCap.SetResult(new Proxy(LazyCapability.CreateBrokenCap(message))); #endif if (_pendingCallsOnPromise == 0) { release = true; _released = true; } } if (release) { _ep.ReleaseImport(_remoteId); } }