private static void CheckPriorityQueue(PriorityNodeQueue<int> priorityQueue)
 {
     int lastItem = int.MinValue;
     while (!priorityQueue.Empty)
     {
         var value = priorityQueue.Dequeue();
         Assert.That(value, Is.GreaterThanOrEqualTo(lastItem));
         lastItem = value;
     }
 }
Пример #2
0
        private static void CheckPriorityQueue(PriorityNodeQueue <int> priorityQueue)
        {
            int lastItem = int.MinValue;

            while (!priorityQueue.Empty)
            {
                var value = priorityQueue.Dequeue();
                Assert.True(value >= lastItem);
                lastItem = value;
            }
        }
Пример #3
0
        private static void CheckPriorityQueue(PriorityNodeQueue <int> priorityQueue)
        {
            int lastItem = int.MinValue;

            while (!priorityQueue.Empty)
            {
                var value = priorityQueue.Dequeue();
                Assert.That(value, Is.GreaterThanOrEqualTo(lastItem));
                lastItem = value;
            }
        }
Пример #4
0
        private BuildStep GetNextBuildStep(int maxPriority)
        {
            while (true)
            {
                AssetBuildUnit unit;
                lock (queueLock)
                {
                    if (queue.Empty)
                    {
                        return(null);
                    }
                    unit = queue.Dequeue();
                }

                // Check that priority is good enough
                if (unit.PriorityMajor > maxPriority)
                {
                    return(null);
                }

                var buildStep = unit.GetBuildStep();

                // If this build step couldn't be built, let's find another one
                if (buildStep == null)
                {
                    continue;
                }

                // Forward priority to build engine (still very coarse, but should help)
                buildStep.Priority = unit.PriorityMajor;

                foreach (var step in buildStep.EnumerateRecursively())
                {
                    var assetStep = step as AssetBuildStep;
                    if (assetStep != null)
                    {
                        assetStep.Priority       = unit.PriorityMajor;
                        assetStep.StepProcessed += (s, e) => NotifyAssetBuilt(assetStep.AssetItem, assetStep.Logger);
                    }
                }

                return(buildStep);
            }
        }
Пример #5
0
        /// <summary>
        /// Runs until no runnable tasklets left.
        /// This function is reentrant.
        /// </summary>
        public void Run()
        {
            int managedThreadId = Thread.CurrentThread.ManagedThreadId;

            MicroThreadCallbackList callbacks = default(MicroThreadCallbackList);

            while (true)
            {
                SchedulerEntry schedulerEntry;
                MicroThread    microThread;
                lock (ScheduledEntries)
                {
                    // Reclaim callbacks of previous microthread
                    MicroThreadCallbackNode callback;
                    while (callbacks.TakeFirst(out callback))
                    {
                        callback.Clear();
                        CallbackNodePool.Add(callback);
                    }

                    if (ScheduledEntries.Count == 0)
                    {
                        break;
                    }
                    schedulerEntry = ScheduledEntries.Dequeue();
                    microThread    = schedulerEntry.MicroThread;
                    if (microThread != null)
                    {
                        callbacks             = microThread.Callbacks;
                        microThread.Callbacks = default(MicroThreadCallbackList);
                    }
                }

                // Since it can be reentrant, it should be restored after running the callback.
                var previousRunningMicrothread = runningMicroThread.Value;
                if (previousRunningMicrothread != null)
                {
                    MicroThreadCallbackEnd?.Invoke(this, new SchedulerThreadEventArgs(previousRunningMicrothread, managedThreadId));
                }

                runningMicroThread.Value = microThread;

                if (microThread != null)
                {
                    var previousSyncContext = SynchronizationContext.Current;
                    SynchronizationContext.SetSynchronizationContext(microThread.SynchronizationContext);

                    // TODO: Do we still need to try/catch here? Everything should be caught in the continuation wrapper and put into MicroThread.Exception
                    try
                    {
                        if (microThread.State == MicroThreadState.Starting)
                        {
                            MicroThreadStarted?.Invoke(this, new SchedulerThreadEventArgs(microThread, managedThreadId));
                        }

                        MicroThreadCallbackStart?.Invoke(this, new SchedulerThreadEventArgs(microThread, managedThreadId));

                        var profilingKey = microThread.ProfilingKey ?? schedulerEntry.ProfilingKey ?? MicroThreadProfilingKeys.ProfilingKey;
                        using (Profiler.Begin(profilingKey))
                        {
                            var callback = callbacks.First;
                            while (callback != null)
                            {
                                callback.Invoke();
                                callback = callback.Next;
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        Log.Error("Unexpected exception while executing a micro-thread", e);
                        microThread.SetException(e);
                    }
                    finally
                    {
                        MicroThreadCallbackEnd?.Invoke(this, new SchedulerThreadEventArgs(microThread, managedThreadId));

                        SynchronizationContext.SetSynchronizationContext(previousSyncContext);
                        if (microThread.IsOver)
                        {
                            lock (microThread.AllLinkedListNode)
                            {
                                if (microThread.CompletionTask != null)
                                {
                                    if (microThread.State == MicroThreadState.Failed || microThread.State == MicroThreadState.Canceled)
                                    {
                                        microThread.CompletionTask.TrySetException(microThread.Exception);
                                    }
                                    else
                                    {
                                        microThread.CompletionTask.TrySetResult(1);
                                    }
                                }
                                else if (microThread.State == MicroThreadState.Failed && microThread.Exception != null)
                                {
                                    // Nothing was listening on the micro thread and it crashed
                                    // Let's treat it as unhandled exception and propagate it
                                    // Use ExceptionDispatchInfo.Capture to not overwrite callstack
                                    if (PropagateExceptions && (microThread.Flags & MicroThreadFlags.IgnoreExceptions) != MicroThreadFlags.IgnoreExceptions)
                                    {
                                        ExceptionDispatchInfo.Capture(microThread.Exception).Throw();
                                    }
                                }

                                MicroThreadEnded?.Invoke(this, new SchedulerThreadEventArgs(microThread, managedThreadId));
                            }
                        }

                        runningMicroThread.Value = previousRunningMicrothread;
                        if (previousRunningMicrothread != null)
                        {
                            MicroThreadCallbackStart?.Invoke(this, new SchedulerThreadEventArgs(previousRunningMicrothread, managedThreadId));
                        }
                    }
                }
                else
                {
                    try
                    {
                        var profilingKey = schedulerEntry.ProfilingKey ?? MicroThreadProfilingKeys.ProfilingKey;
                        using (Profiler.Begin(profilingKey))
                        {
                            schedulerEntry.Action();
                        }
                    }
                    catch (Exception e)
                    {
                        ActionException?.Invoke(this, schedulerEntry, e);
                    }
                }
            }

            while (FrameChannel.Balance < 0)
            {
                FrameChannel.Send(0);
            }
        }
Пример #6
0
        /// <summary>
        /// Runs until no runnable tasklets left.
        /// This function is reentrant.
        /// </summary>
        public void Run()
        {
#if SILICONSTUDIO_PLATFORM_WINDOWS_RUNTIME
            int managedThreadId = 0;
#else
            int managedThreadId = Thread.CurrentThread.ManagedThreadId;
#endif

            while (true)
            {
                Action      callback;
                MicroThread microThread;
                lock (scheduledMicroThreads)
                {
                    if (scheduledMicroThreads.Count == 0)
                    {
                        break;
                    }
                    microThread = scheduledMicroThreads.Dequeue();

                    callback             = microThread.Callback;
                    microThread.Callback = null;
                }

                // Since it can be reentrant, it should be restored after running the callback.
                var previousRunningMicrothread = runningMicroThread.Value;
                if (previousRunningMicrothread != null)
                {
                    if (MicroThreadCallbackEnd != null)
                    {
                        MicroThreadCallbackEnd(this, new SchedulerThreadEventArgs(previousRunningMicrothread, managedThreadId));
                    }
                }

                runningMicroThread.Value = microThread;
                var previousSyncContext = SynchronizationContext.Current;
                SynchronizationContext.SetSynchronizationContext(microThread.SynchronizationContext);
                try
                {
                    if (microThread.State == MicroThreadState.Starting && MicroThreadStarted != null)
                    {
                        MicroThreadStarted(this, new SchedulerThreadEventArgs(microThread, managedThreadId));
                    }

                    if (MicroThreadCallbackStart != null)
                    {
                        MicroThreadCallbackStart(this, new SchedulerThreadEventArgs(microThread, managedThreadId));
                    }

                    using (Profiler.Begin(microThread.ProfilingKey))
                    {
                        callback();
                    }
                }
                catch (Exception e)
                {
                    Log.Error("Unexpected exception while executing a micro-thread", e);
                    microThread.SetException(e);
                }
                finally
                {
                    if (MicroThreadCallbackEnd != null)
                    {
                        MicroThreadCallbackEnd(this, new SchedulerThreadEventArgs(microThread, managedThreadId));
                    }

                    SynchronizationContext.SetSynchronizationContext(previousSyncContext);
                    if (microThread.IsOver)
                    {
                        lock (microThread.AllLinkedListNode)
                        {
                            if (microThread.CompletionTask != null)
                            {
                                if (microThread.State == MicroThreadState.Failed || microThread.State == MicroThreadState.Cancelled)
                                {
                                    microThread.CompletionTask.TrySetException(microThread.Exception);
                                }
                                else
                                {
                                    microThread.CompletionTask.TrySetResult(1);
                                }
                            }
                            else if (microThread.State == MicroThreadState.Failed && microThread.Exception != null)
                            {
                                // Nothing was listening on the micro thread and it crashed
                                // Let's treat it as unhandled exception and propagate it
                                // Use ExceptionDispatchInfo.Capture to not overwrite callstack
                                if ((microThread.Flags & MicroThreadFlags.IgnoreExceptions) != MicroThreadFlags.IgnoreExceptions)
                                {
                                    ExceptionDispatchInfo.Capture(microThread.Exception).Throw();
                                }
                            }

                            if (MicroThreadEnded != null)
                            {
                                MicroThreadEnded(this, new SchedulerThreadEventArgs(microThread, managedThreadId));
                            }
                        }
                    }

                    runningMicroThread.Value = previousRunningMicrothread;
                    if (previousRunningMicrothread != null)
                    {
                        if (MicroThreadCallbackStart != null)
                        {
                            MicroThreadCallbackStart(this, new SchedulerThreadEventArgs(previousRunningMicrothread, managedThreadId));
                        }
                    }
                }
            }

            while (FrameChannel.Balance < 0)
            {
                FrameChannel.Send(0);
            }
        }