public bool MoveNext() { if (false == _flushingOperation.stopped) //don't start anything while flushing { _flushTaskDel(_newTaskRoutines, _coroutines, _flushingOperation); } else if (_runnerBehaviourForUnityCoroutine != null) { _runnerBehaviourForUnityCoroutine.StopAllCoroutines(); } UnityEngine.Profiling.Profiler.BeginSample(_info.runnerName); for (int i = 0; _info.MoveNext(i, _coroutines.Count); i++) { var pausableTask = _coroutines[i]; //let's spend few words on this. //yielded YieldInstruction and AsyncOperation can //only be processed internally by Unity. //The simplest way to handle them is to hand them to Unity itself. //However while the Unity routine is processed, the rest of the //coroutine is waiting for it. This would defeat the purpose //of the parallel procedures. For this reason, a Parallel //task will mark the enumerator returned as ParallelYield which //will change the way the routine is processed. //in this case the MonoRunner won't wait for the Unity routine //to continue processing the next tasks. //Note that it is much better to return wrap AsyncOperation around //custom IEnumerator classes then returning them directly as //most of the time they don't need to be handled by Unity as //YieldInstructions do /// /// Handle special Unity instructions /// you should avoid them or wrap them /// around custom IEnumerator to avoid /// the cost of two allocations per instruction /// if (_runnerBehaviourForUnityCoroutine != null && _flushingOperation.stopped == false) { var current = pausableTask.Current; if (current is YieldInstruction) { var handItToUnity = new HandItToUnity (current, pausableTask, _resumeOperation, _flushingOperation); //remove the special instruction. it will //be added back once Unity completes. _coroutines.UnorderedRemoveAt(i--); var coroutine = _runnerBehaviourForUnityCoroutine.StartCoroutine (handItToUnity.GetEnumerator()); (pausableTask as PausableTask).onExplicitlyStopped = () => { _runnerBehaviourForUnityCoroutine.StopCoroutine(coroutine); handItToUnity.ForceStop(); }; continue; } var parallelTask = (current as ParallelTaskCollection.ParallelTask); if (parallelTask != null && parallelTask.current is YieldInstruction) { var handItToUnity = new HandItToUnity(parallelTask.current); parallelTask.Add(handItToUnity.WaitUntilIsDone()); var coroutine = _runnerBehaviourForUnityCoroutine.StartCoroutine (handItToUnity.GetEnumerator()); (pausableTask as PausableTask).onExplicitlyStopped = () => { _runnerBehaviourForUnityCoroutine.StopCoroutine(coroutine); handItToUnity.ForceStop(); }; } } bool result; #if TASKS_PROFILER_ENABLED result = Svelto.Tasks.Profiler.TaskProfiler.MonitorUpdateDuration(pausableTask, _info.runnerName); #else #if PROFILER UnityEngine.Profiling.Profiler.BeginSample(_info.runnerName.FastConcat("+", pausableTask.ToString())); #endif result = pausableTask.MoveNext(); #if PROFILER UnityEngine.Profiling.Profiler.EndSample(); #endif #endif if (result == false) { var disposable = pausableTask as IDisposable; if (disposable != null) { disposable.Dispose(); } _coroutines.UnorderedRemoveAt(i--); } } UnityEngine.Profiling.Profiler.EndSample(); if (_flushingOperation.stopped == true && _coroutines.Count == 0) { //once all the coroutines are flushed //the loop can return accepting new tasks _flushingOperation.stopped = false; } return(true); }
internal static IEnumerator Process( ThreadSafeQueue <IPausableTask> newTaskRoutines, FasterList <IPausableTask> coroutines, FlushingOperation flushingOperation, RunningTasksInfo info, FlushTasksDel flushTaskDel, RunnerBehaviour runnerBehaviourForUnityCoroutine, Action <IPausableTask> resumeOperation) { while (true) { if (false == flushingOperation.stopped) //don't start anything while flushing { flushTaskDel(newTaskRoutines, coroutines, flushingOperation); } else if (runnerBehaviourForUnityCoroutine != null) { runnerBehaviourForUnityCoroutine.StopAllCoroutines(); } info.count = coroutines.Count; for (var i = 0; i < info.count; i++) { var pausableTask = coroutines[i]; //let's spend few words on this. //yielded YieldInstruction and AsyncOperation can //only be processed internally by Unity. //The simplest way to handle them is to hand them to Unity itself. //However while the Unity routine is processed, the rest of the //coroutine is waiting for it. This would defeat the purpose //of the parallel procedures. For this reason, a Parallel //task will mark the enumerator returned as ParallelYield which //will change the way the routine is processed. //in this case the MonoRunner won't wait for the Unity routine //to continue processing the next tasks. //Note that it is much better to return wrap AsyncOperation around //custom IEnumerator classes then returning them directly as //most of the time they don't need to be handled by Unity as //YieldInstructions do /// /// Handle special Unity instructions /// you should avoid them or wrap them /// around custom IEnumerator to avoid /// the cost of two allocations per instruction /// if (runnerBehaviourForUnityCoroutine != null && flushingOperation.stopped == false) { var current = pausableTask.Current; if (current is YieldInstruction) { var handItToUnity = new HandItToUnity (current, pausableTask, resumeOperation, flushingOperation); //remove the special instruction. it will //be added back once Unity completes. coroutines.UnorderedRemoveAt(i--); info.count = coroutines.Count; var coroutine = runnerBehaviourForUnityCoroutine.StartCoroutine (handItToUnity.GetEnumerator()); (pausableTask as PausableTask).onExplicitlyStopped = () => { runnerBehaviourForUnityCoroutine.StopCoroutine(coroutine); handItToUnity.ForceStop(); }; continue; } var parallelTask = (current as ParallelTaskCollection.ParallelTask); if (parallelTask != null && parallelTask.current is YieldInstruction) { var handItToUnity = new HandItToUnity(parallelTask.current); parallelTask.Add(handItToUnity.WaitUntilIsDone()); var coroutine = runnerBehaviourForUnityCoroutine.StartCoroutine (handItToUnity.GetEnumerator()); (pausableTask as PausableTask).onExplicitlyStopped = () => { runnerBehaviourForUnityCoroutine.StopCoroutine(coroutine); handItToUnity.ForceStop(); }; } } bool result; #if TASKS_PROFILER_ENABLED && UNITY_EDITOR result = TASK_PROFILER.MonitorUpdateDuration(pausableTask, info.runnerName); #else result = pausableTask.MoveNext(); #endif if (result == false) { var disposable = pausableTask as IDisposable; if (disposable != null) { disposable.Dispose(); } coroutines.UnorderedRemoveAt(i--); } info.count = coroutines.Count; } if (flushingOperation.stopped == true && coroutines.Count == 0) { //once all the coroutines are flushed //the loop can return accepting new tasks flushingOperation.stopped = false; } yield return(null); } }