Esempio n. 1
0
        public void AwaitUnsafeOnCompleted <TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine)
            where TAwaiter : ICriticalNotifyCompletion
            where TStateMachine : IAsyncStateMachine
        {
            try
            {
                if (_stateMachine == null)
                {
                    var ignored = Task; // NB: Ensure we have the observable backed by an async subject ready.

                    _stateMachine = stateMachine;
                    _stateMachine.SetStateMachine(_stateMachine);
                }

                // NB: Rx has historically not bothered with execution contexts, so we don't do it here either.

                awaiter.UnsafeOnCompleted(_stateMachine.MoveNext);
            }
            catch (Exception ex)
            {
                // NB: Prevent reentrancy into the async state machine when an exception would be observed
                //     by the caller. This could cause concurrent execution of the async method. Instead,
                //     rethrow the exception elsewhere.

                Rethrow(ex);
            }
        }
Esempio n. 2
0
        /// <summary>
        /// Gets the Action to use with an awaiter's OnCompleted or UnsafeOnCompleted method.
        /// On first invocation, the supplied state machine will be boxed.
        /// </summary>
        /// <typeparam name="TMethodBuilder">Specifies the type of the method builder used.</typeparam>
        /// <typeparam name="TStateMachine">Specifies the type of the state machine used.</typeparam>
        /// <param name="builder">The builder.</param>
        /// <param name="stateMachine">The state machine.</param>
        /// <returns>An Action to provide to the awaiter.</returns>
#if !SILVERLIGHT
        // [SecuritySafeCritical]
#endif
        internal Action GetCompletionAction <TMethodBuilder, TStateMachine>(
            ref TMethodBuilder builder, ref TStateMachine stateMachine)
            where TMethodBuilder : IAsyncMethodBuilder
            where TStateMachine : IAsyncStateMachine
        {
            // The builder needs to flow ExecutionContext, so capture it.
            var capturedContext = ExecutionContextLightup.Instance.Capture();

            MoveNextRunner runner = new MoveNextRunner(capturedContext);
            Action         action = new Action(runner.Run);

            // If this is our first await, such that we've not yet boxed the state machine, do so now.
            if (m_stateMachine == null)
            {
                // This is our first await, and we're not boxed yet.  First performance any work that
                // must affect both the non-boxed and boxed builders.
                builder.PreBoxInitialization();

                // Box the state machine, then tell the boxed instance to call back into its own builder,
                // so we can cache the boxed reference.
                m_stateMachine = (IAsyncStateMachine)stateMachine;
                m_stateMachine.SetStateMachine(m_stateMachine);
            }

            // Now that we have the state machine, store it into the runner that the action delegate points to.
            // And return the action.
            runner.m_stateMachine = m_stateMachine; // only after this line is the Action delegate usable
            return(action);
        }
Esempio n. 3
0
            private void SetTCS(IAsyncStateMachine machine, TaskCompletionSource <T> tcs)
            {
                // Option 1: (works only in release mode)
                // TODO: measure if it is any faster
                tcsGlobalSignal = tcs;
                machine.SetStateMachine(machine);
                if (tcsGlobalSignal is object)
                {
                    IOTaskMethodBuilder <T> newBuilder;
                    newBuilder.preboxedMachine = machine;
                    newBuilder.tcs             = tcs;
                    newBuilder.boxedMoveNext   = null;
                    newBuilder.resultIO        = this;
                    // TODO: add preboxed machine

                    tcsGlobalSignal = null;

                    machine.GetType().GetField("<>t__builder").SetValue(machine, newBuilder);

                    // // Using DLR
                    // // https://sharplab.io/#v2:D4AQTAjAsAULBuBDATgAgCaoLyoHYFMB3DAFgAoBKAblgGEA6AWTPQBoN8AzRAVwBsALtVjp6ASVwBnAA74AxgMo04MSfkR98mcKVgBvWAEgQAZlQBLXANSSBiAfmWxUL1KdSMAngGUByHgqoAgBGPOZ86PjIyq6osAC+sLC2/oFevqnWBjCx7pbWAB7KiSo6tKjZsW5mIBAAbG4kHmQA8sEAVvLWiOzpfgGFFBXOVbFkLJ64iAC25nIUiBT0IWERUdioRSOuJfFAA==

                    // if (callSiteCache is null)
                    // {
                    //     Type context = typeof(BuiltIO);
                    //     var args = new CSharpArgumentInfo[] {
                    //         CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null),
                    //         CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.UseCompileTimeType, null)
                    //     };

                    //     callSiteCache = CallSite<Func<CallSite, object, IOTaskMethodBuilder<T>, object>>.Create(Microsoft.CSharp.RuntimeBinder.Binder.SetMember(CSharpBinderFlags.None, "<>t__builder", context, args));
                    // }
                    // callSiteCache.Target(callSiteCache, machine, newBuilder);
                }
            }
Esempio n. 4
0
        Action GetCompletionAction <TStateMachine> (ref TStateMachine machine) where TStateMachine : IAsyncStateMachine
        {
            // If this is our first await, such that we've not yet boxed the state machine, do so now.
            if (stateMachine == null)
            {
                stateMachine = (IAsyncStateMachine)machine;
                stateMachine.SetStateMachine(stateMachine);
            }
            var runner = new Runner(stateMachine, scope);

            return(new Action(runner.Run));
        }
Esempio n. 5
0
        internal Action GetCompletionAction <TMethodBuilder, TStateMachine>(TMethodBuilder builder,
                                                                            TStateMachine stateMachine) where TMethodBuilder : IAsyncMethodBuilder
            where TStateMachine : IAsyncStateMachine
        {
            if (m_stateMachine == null)
            {
                m_stateMachine = stateMachine;
                m_stateMachine.SetStateMachine(m_stateMachine);
            }
            Action action = m_stateMachine.MoveNext;

            return(action);
        }
Esempio n. 6
0
        internal Action GetCompletionAction <TMethodBuilder, TStateMachine>(ref TMethodBuilder builder, ref TStateMachine stateMachine) where TMethodBuilder : IAsyncMethodBuilder where TStateMachine : IAsyncStateMachine
        {
            var context        = ExecutionContextLightup.Instance.Capture();
            var moveNextRunner = new MoveNextRunner(context);
            var result         = new Action(moveNextRunner.Run);

            if (m_stateMachine == null)
            {
                builder.PreBoxInitialization();
                m_stateMachine = stateMachine;
                m_stateMachine.SetStateMachine(m_stateMachine);
            }
            moveNextRunner.m_stateMachine = m_stateMachine;
            return(result);
        }
        internal Action GetCompletionAction <TMethodBuilder, TStateMachine>(ref TMethodBuilder builder, ref TStateMachine stateMachine)
            where TMethodBuilder : IAsyncMethodBuilder
            where TStateMachine : IAsyncStateMachine
        {
            var    moveNextRunner = new MoveNextRunner(ExecutionContext.Capture());
            Action action         = moveNextRunner.Run;

            if (m_stateMachine == null)
            {
                builder.PreBoxInitialization();
                m_stateMachine = stateMachine;
                m_stateMachine.SetStateMachine(m_stateMachine);
            }
            moveNextRunner.m_stateMachine = m_stateMachine;
            return(action);
        }
        /// <summary>
        /// Gets the <see cref="Action"/> to use with an awaiter's <see cref="INotifyCompletion.OnCompleted"/> or
        /// <see cref="ICriticalNotifyCompletion.UnsafeOnCompleted"/> method. On first invocation, the supplied state
        /// machine will be boxed.
        /// </summary>
        /// <typeparam name="TMethodBuilder">Specifies the type of the method builder used.</typeparam>
        /// <typeparam name="TStateMachine">Specifies the type of the state machine used.</typeparam>
        /// <param name="builder">The builder.</param>
        /// <param name="stateMachine">The state machine.</param>
        /// <returns>An <see cref="Action"/> to provide to the awaiter.</returns>
        internal Action GetCompletionAction <TMethodBuilder, TStateMachine>(ref TMethodBuilder builder, ref TStateMachine stateMachine)
            where TMethodBuilder : IAsyncMethodBuilder
            where TStateMachine : IAsyncStateMachine
        {
            ExecutionContext context        = ExecutionContext.Capture();
            MoveNextRunner   moveNextRunner = new MoveNextRunner(context);
            Action           result         = moveNextRunner.Run;

            if (_stateMachine == null)
            {
                builder.PreBoxInitialization(ref stateMachine);
                _stateMachine = stateMachine;
                _stateMachine.SetStateMachine(_stateMachine);
            }

            moveNextRunner._stateMachine = _stateMachine;
            return(result);
        }
Esempio n. 9
0
        internal void PostBoxInitialization <TResult>(IAsyncStateMachine stateMachine, MoveNextRunner runner, Task builtTask, TaskCompletionSource <TResult> tcs)
        {
            if (builtTask != null)
            {
            }

            m_stateMachine = stateMachine;
            m_stateMachine.SetStateMachine(m_stateMachine);

            ((IBuilderStateMachine <TResult>)m_stateMachine).SetBuilderTcs(tcs);

            Contract.Assert(runner.m_stateMachine == null, "The runner's state machine should not yet have been populated.");
            Contract.Assert(m_stateMachine != null, "The builder's state machine field should have been initialized.");

            // Now that we have the state machine, store it into the runner that the action delegate points to.
            // And return the action.
            runner.m_stateMachine = m_stateMachine; // only after this line is the Action delegate usable
        }
Esempio n. 10
0
        /// <summary>
        /// Gets the <see cref="Action"/> to use with an awaiter's <see cref="INotifyCompletion.OnCompleted"/> or
        /// <see cref="ICriticalNotifyCompletion.UnsafeOnCompleted"/> method. On first invocation, the supplied state
        /// machine will be boxed.
        /// </summary>
        /// <typeparam name="TMethodBuilder">Specifies the type of the method builder used.</typeparam>
        /// <typeparam name="TStateMachine">Specifies the type of the state machine used.</typeparam>
        /// <param name="builder">The builder.</param>
        /// <param name="stateMachine">The state machine.</param>
        /// <returns>An <see cref="Action"/> to provide to the awaiter.</returns>
#if !SILVERLIGHT
        //// [SecuritySafeCritical]
#endif
        internal Action GetCompletionAction<TMethodBuilder, TStateMachine>(ref TMethodBuilder builder, ref TStateMachine stateMachine)
            where TMethodBuilder : IAsyncMethodBuilder
            where TStateMachine : IAsyncStateMachine
        {
            Debug.Assert(builder != null, "Expected valid builder");
            Debug.Assert(stateMachine != null, "Expected valid state machine reference");

            // The builder needs to flow ExecutionContext, so capture it.
            var capturedContext = ExecutionContextLightup.Instance.Capture();

            MoveNextRunner runner = new MoveNextRunner(capturedContext);
            Action action = new Action(runner.Run);

            // If this is our first await, such that we've not yet boxed the state machine, do so now.
            if (_stateMachine == null)
            {
                // This is our first await, and we're not boxed yet. First performance any work that must affect both
                // the non-boxed and boxed builders.
                builder.PreBoxInitialization();

                // Box the state machine, then tell the boxed instance to call back into its own builder, so we can
                // cache the boxed reference.
                Debug.Assert(!object.ReferenceEquals((object)stateMachine, (object)stateMachine), "Expected an unboxed state machine reference");
                _stateMachine = stateMachine;
                _stateMachine.SetStateMachine(_stateMachine);
            }

            Debug.Assert(runner._stateMachine == null, "The runner's state machine should not yet have been populated.");
            Debug.Assert(_stateMachine != null, "The builder's state machine field should have been initialized.");

            // Now that we have the state machine, store it into the runner that the action delegate points to. And
            // return the action.
            //
            // Only after this line is the Action delegate usable.
            runner._stateMachine = _stateMachine;
            return action;
        }