Ejemplo n.º 1
0
        public void EmitAwaitOnCompletedDynamic(EmitContext ec, FieldExpr awaiter)
        {
            var critical = Module.PredefinedTypes.ICriticalNotifyCompletion;

            if (!critical.Define())
            {
                throw new NotImplementedException();
            }

            var temp_critical  = new LocalTemporary(critical.TypeSpec);
            var label_critical = ec.DefineLabel();
            var label_end      = ec.DefineLabel();

            //
            // Special path for dynamic awaiters
            //
            // var awaiter = this.$awaiter as ICriticalNotifyCompletion;
            // if (awaiter == null) {
            //    var completion = (INotifyCompletion) this.$awaiter;
            //    this.$builder.AwaitOnCompleted (ref completion, ref this);
            // } else {
            //    this.$builder.AwaitUnsafeOnCompleted (ref awaiter, ref this);
            // }
            //
            awaiter.Emit(ec);
            ec.Emit(OpCodes.Isinst, critical.TypeSpec);
            temp_critical.Store(ec);
            temp_critical.Emit(ec);
            ec.Emit(OpCodes.Brtrue_S, label_critical);

            var temp = new LocalTemporary(Module.PredefinedTypes.INotifyCompletion.TypeSpec);

            awaiter.Emit(ec);
            ec.Emit(OpCodes.Castclass, temp.Type);
            temp.Store(ec);
            EmitOnCompleted(ec, temp, false);
            temp.Release(ec);
            ec.Emit(OpCodes.Br_S, label_end);

            ec.MarkLabel(label_critical);

            EmitOnCompleted(ec, temp_critical, true);

            ec.MarkLabel(label_end);

            temp_critical.Release(ec);
        }
Ejemplo n.º 2
0
        public Expression EmitContinuationInitialization(EmitContext ec)
        {
            //
            // When more than 1 awaiter has been used in the block we
            // introduce class scope field to cache continuation delegate
            //
            if (awaiters > 1)
            {
                if (continuation == null)
                {
                    continuation = AddCompilerGeneratedField("$continuation", new TypeExpression(action, Location), true);
                    continuation.Define();
                }

                var fexpr = new FieldExpr(continuation, Location);
                fexpr.InstanceExpression = new CompilerGeneratedThis(CurrentType, Location);

                //
                // if ($continuation == null)
                //    $continuation = new Action (MoveNext);
                //
                fexpr.Emit(ec);

                var skip_cont_init = ec.DefineLabel();
                ec.Emit(OpCodes.Brtrue_S, skip_cont_init);

                ec.EmitThis();
                EmitActionLoad(ec);
                ec.Emit(OpCodes.Stfld, continuation.Spec);
                ec.MarkLabel(skip_cont_init);

                return(fexpr);
            }

            //
            // Otherwise simply use temporary local variable
            //
            var field = LocalVariable.CreateCompilerGenerated(action, OriginalSourceBlock, Location);

            EmitActionLoad(ec);
            field.EmitAssign(ec);
            return(new LocalVariableReference(field, Location));
        }