Beispiel #1
0
        public bool TryEnterOnCurrentStack()
        {
#if NETFRAMEWORK || NETSTANDARD2_0
            try
            {
                RuntimeHelpers.EnsureSufficientExecutionStack();
                return(true);
            }
            catch (InsufficientExecutionStackException)
            {
            }
#else
            if (RuntimeHelpers.TryEnsureSufficientExecutionStack())
            {
                return(true);
            }
#endif

            if (_executionStackCount < MaxExecutionStackCount)
            {
                return(false);
            }

            throw new InsufficientExecutionStackException();
        }
        public bool TryEnterOnCurrentStack()
        {
#if NETCOREAPP2_0
            if (RuntimeHelpers.TryEnsureSufficientExecutionStack())
            {//尝试确保有足够的堆栈来执行平均 .NET Core 库函数
                return(true);
            }
#else
            try
            {
                RuntimeHelpers.EnsureSufficientExecutionStack();//确保剩余的堆栈控件足够大,可以执行一般的 .NET 函数
                return(true);
            }
            catch (InsufficientExecutionStackException)
            {
            }
#endif

            if (_executionStackCount < MaxExecutionStackCount)
            {
                return(false);
            }

            throw new InsufficientExecutionStackException();
        }
Beispiel #3
0
        /// <inheritdoc/>
        public void Execute(ResolveRequestContext context, Action <ResolveRequestContext> next)
        {
            if (!(context.Operation is IDependencyTrackingResolveOperation dependencyTrackingResolveOperation))
            {
                // Skipping circular dependency detection, since IResolveOperation is not IDependencyTrackingResolveOperation
                // Which contains the actual RequestStack using SegmentStack
                next(context);
                return;
            }

            var activationDepth = context.Operation.RequestDepth;

            if (activationDepth > _maxResolveDepth)
            {
#if NETSTANDARD2_1
                // In .NET Standard 2.1 we will try and keep going until we run out of stack space.
                if (!RuntimeHelpers.TryEnsureSufficientExecutionStack())
                {
                    throw new DependencyResolutionException(string.Format(CultureInfo.CurrentCulture, CircularDependencyDetectorMessages.MaxDepthExceeded, context.Service));
                }
#else
                // Pre .NET Standard 2.1 we just end at 50.
                throw new DependencyResolutionException(string.Format(CultureInfo.CurrentCulture, CircularDependencyDetectorMessages.MaxDepthExceeded, context.Service));
#endif
            }

            var requestStack = dependencyTrackingResolveOperation.RequestStack;

            // The first one is the current resolve request.
            // Do our circular dependency check.
            if (activationDepth > 1)
            {
                var registration = context.Registration;

                foreach (var requestEntry in requestStack)
                {
                    if (requestEntry.Registration == registration)
                    {
                        throw new DependencyResolutionException(string.Format(
                                                                    CultureInfo.CurrentCulture,
                                                                    CircularDependencyDetectorMessages.CircularDependency,
                                                                    CreateDependencyGraphTo(registration, requestStack)));
                    }
                }
            }

            requestStack.Push(context);

            try
            {
                // Circular dependency check is done, move to the next stage.
                next(context);
            }
            finally
            {
                requestStack.Pop();
            }
        }
Beispiel #4
0
        public bool TryEnterOnCurrentStack()
        {
            if (RuntimeHelpers.TryEnsureSufficientExecutionStack())
            {
                return(true);
            }

            if (_executionStackCount < MaxExecutionStackCount)
            {
                return(false);
            }

            throw new InsufficientExecutionStackException();
        }
Beispiel #5
0
 private static void FillStack(int depth)
 {
     // This test will fail with a StackOverflowException if TryEnsureSufficientExecutionStack() doesn't
     // return false. No exception is thrown and the test finishes when TryEnsureSufficientExecutionStack()
     // returns true.
     if (!RuntimeHelpers.TryEnsureSufficientExecutionStack())
     {
         Assert.Throws <InsufficientExecutionStackException>(() => RuntimeHelpers.EnsureSufficientExecutionStack());
         return;
     }
     else if (depth < 2048)
     {
         FillStack(depth + 1);
     }
 }
Beispiel #6
0
        /// <summary>Tries to ensure there is sufficient stack to execute the average .NET function.</summary>
        public static bool TryEnsureSufficientExecutionStack()
        {
#if REGEXGENERATOR
            try
            {
                RuntimeHelpers.EnsureSufficientExecutionStack();
                return(true);
            }
            catch
            {
                return(false);
            }
#else
            return(RuntimeHelpers.TryEnsureSufficientExecutionStack());
#endif
        }
        /// <summary>Copies that ending state information from <paramref name="task"/> to <paramref name="completionSource"/>.</summary>
        private static bool TrySetFromTask <TResult>(this TaskCompletionSource <TResult> completionSource, Task task)
        {
            Debug.Assert(task.IsCompleted);

            // Before transferring the results, check to make sure we're not too deep on the stack.  Calling TrySet*
            // will cause any synchronous continuations to be invoked, which is fine unless we're so deep that doing
            // so overflows.  ContinueWith has built-in support for avoiding such stack dives, but that support is not
            // (yet) part of await's infrastructure, so until it is we mimic it manually.  This matches the behavior
            // employed by the Unwrap implementation in mscorlib.
            if (!RuntimeHelpers.TryEnsureSufficientExecutionStack())
            {
                // This is very rare.  We're too deep to safely invoke
                // TrySet* synchronously, so do so asynchronously instead.
                Task.Factory.StartNew(s =>
                {
                    var t = (Tuple <TaskCompletionSource <TResult>, Task>)s;
                    TrySetFromTask(t.Item1, t.Item2);
                }, Tuple.Create(completionSource, task), CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default);
                return(true);
            }

            // Transfer the results from the supplied Task to the TaskCompletionSource.
            bool result = false;

            switch (task.Status)
            {
            case TaskStatus.Canceled:
                result = completionSource.TrySetCanceled(ExtractCancellationToken(task));
                break;

            case TaskStatus.Faulted:
                result = completionSource.TrySetException(task.Exception.InnerExceptions);
                break;

            case TaskStatus.RanToCompletion:
                Task <TResult> resultTask = task as Task <TResult>;
                result = resultTask != null?
                         completionSource.TrySetResult(resultTask.Result) :
                             completionSource.TrySetResult(default(TResult));

                break;
            }
            return(result);
        }
        ////////////////////////////////////////////////////////////
        //
        // Internal overridable methods
        //


        /// <summary>
        /// Attempts to execute the target task synchronously.
        /// </summary>
        /// <param name="task">The task to run.</param>
        /// <param name="taskWasPreviouslyQueued">True if the task may have been previously queued,
        /// false if the task was absolutely not previously queued.</param>
        /// <returns>True if it ran, false otherwise.</returns>
        internal bool TryRunInline(Task task, bool taskWasPreviouslyQueued)
        {
            // Do not inline unstarted tasks (i.e., task.ExecutingTaskScheduler == null).
            // Do not inline TaskCompletionSource-style (a.k.a. "promise") tasks.
            // No need to attempt inlining if the task body was already run (i.e. either TASK_STATE_DELEGATE_INVOKED or TASK_STATE_CANCELED bits set)
            TaskScheduler?ets = task.ExecutingTaskScheduler;

            // Delegate cross-scheduler inlining requests to target scheduler
            if (ets != this && ets != null)
            {
                return(ets.TryRunInline(task, taskWasPreviouslyQueued));
            }

            if ((ets == null) ||
                (task.m_action == null) ||
                task.IsDelegateInvoked ||
                task.IsCanceled ||
                !RuntimeHelpers.TryEnsureSufficientExecutionStack())
            {
                return(false);
            }

            // Task class will still call into TaskScheduler.TryRunInline rather than TryExecuteTaskInline() so that
            // 1) we can adjust the return code from TryExecuteTaskInline in case a buggy custom scheduler lies to us
            // 2) we maintain a mechanism for the TLS lookup optimization that we used to have for the ConcRT scheduler (will potentially introduce the same for TP)
            if (TplEventSource.Log.IsEnabled())
            {
                task.FireTaskScheduledIfNeeded(this);
            }

            bool inlined = TryExecuteTaskInline(task, taskWasPreviouslyQueued);

            // If the custom scheduler returned true, we should either have the TASK_STATE_DELEGATE_INVOKED or TASK_STATE_CANCELED bit set
            // Otherwise the scheduler is buggy
            if (inlined && !(task.IsDelegateInvoked || task.IsCanceled))
            {
                throw new InvalidOperationException(SR.TaskScheduler_InconsistentStateAfterTryExecuteTaskInline);
            }

            return(inlined);
        }
Beispiel #9
0
 public static void TryEnsureSufficientExecutionStack_SpaceAvailable_ReturnsTrue()
 {
     Assert.True(RuntimeHelpers.TryEnsureSufficientExecutionStack());
 }
        protected override WrappedObject TryParse(ParseContext ctx)
        {
            var clone = ctx.Clone();

            ctx.Properties.WrappedObjectCount++;

            var typePattern    = new TypePatternElement();
            var possibleValues = new List <(int CurrentPosition, List <ParseMatch> expression, ParseResult result)>();

            var startPos = clone.CurrentPosition;

            foreach (var type in WorkspaceManager.CurrentWorkspace.TypesManager.KnownTypesFromAddons)
            {
                //Only match once, multiple types are parsed elsewhere
                if (type.IsPlural)
                {
                    continue;
                }
                clone.Matches.Clear();
                clone.CurrentPosition = startPos;
                typePattern.Type      = type.FinalTypeName;
                if (typePattern.ToString().Contains("%object"))
                {
                    Debugger.Break();
                }

                if (!RuntimeHelpers.TryEnsureSufficientExecutionStack())
                {
                    Debugger.Break();
                }

                var result = typePattern.Parse(clone);

                if (result.IsSuccess)
                {
                    var expression = new List <ParseMatch>(clone.Matches);
                    if (expression.Count > 0)
                    {
                        possibleValues.Add((clone.CurrentPosition, expression, result));
                    }
                }
            }

            {
                //clone.ShouldJustCheckExpressionsThatMatchType = true;
                var expressions =
                    WorkspaceManager.CurrentWorkspace.TypesManager.GetExpressionsThatCanFitType(KnownTypesManager
                                                                                                .JavaLangObjectClass);
                if (expressions != null)
                {
                    foreach (var expression in expressions)
                    {
                        foreach (var pattern in expression.PatternNodes)
                        {
                            if (pattern.ToString().Contains("ExprJavaCall"))
                            {
                                Debugger.Break();
                            }
                            clone.Matches.Clear();
                            clone.CurrentPosition = startPos;
                            clone.StartRangeMeasure();
                            var result = pattern.Parse(clone);

                            if (!result.IsSuccess)
                            {
                                clone.UndoRangeMeasure();
                                continue;
                            }

                            var exprResult = clone.Matches;
                            if (exprResult.Count > 0)
                            {
                                var cloneParseContext = clone.Clone();
                                result.Context = cloneParseContext;
                                var expr = new SkriptExpression(expression, clone.EndRangeMeasure(), cloneParseContext);
                                possibleValues.Add((clone.CurrentPosition,
                                                    new List <ParseMatch>(new[] { new ExpressionParseMatch(expr, null) }), result));
                            }
                        }
                    }
                }
            }

            possibleValues.Sort((c1, c2) => - 1 * c1.CurrentPosition.CompareTo(c2.CurrentPosition));

            if (possibleValues.Count <= 0)
            {
                return(null);
            }

            {
                var(lastPos, matches, _) = possibleValues[0];

                ctx.ReadUntilPosition(lastPos);
                ctx.Properties.WrappedObjectCount--;
                return(new WrappedObject(matches));
            }
        }