// Runs a coroutine group then runs the next queued coroutine group if available. // Increments numActive before running the coroutine and decrements it after. // returns values yielded by the given coroutine // coroutineGroup: Coroutine Group to run private IEnumerator CoroutineGroupRunner(CoroutineGroup coroutineGroup) { // increment number of active coroutines numActive++; // save a reference to currently running corouting group runningCoroutineGroup = coroutineGroup; // Run coroutine group coroutineGroup.Run(); // wait while all coroutines in the group are finished while (coroutineGroup.NumberOfCoroutinesToExecute > 0) { // Debug.Log("Coroutine group NumberOfCoroutinesToExecute: " + coroutineGroup.NumberOfCoroutinesToExecute); // skip to the next frame yield return(null); } // coroutine is finished // reset running corouting group reference runningCoroutineGroup = null; // decrement number of active coroutines numActive--; // verify if there still coroutine groups left in a queue if (queue.Count > 0) { // get next coroutine group from the queue var nextCoroutineGroup = queue.Dequeue(); // run next coroutine group Run(nextCoroutineGroup); } }
public static Coroutine StartCoroutine(object obj, IEnumerator coroutine, CoroutineGroup group, string tag = null, bool pool = Coroutine.PoolByDefault) { Coroutine result = null; // Let the caller do this check /*if (!FThreading.IsInGameThread()) * { * FThreading.RunOnGameThread(delegate () { result = StartCoroutine(obj, coroutine, group, tag, pool); }); * return result; * }*/ if (pool) { result = CoroutinePool.New(coroutine); } else { result = new Coroutine(coroutine); } result.Owner = obj; result.Group = group; result.Tag = tag; result.mainCollectionIndex = coroutines.Count; coroutines.Add(result); return(result); }
public static Coroutine StartCoroutine(object obj, IEnumerator coroutine, CoroutineGroup group, string tag = null, bool pool = Coroutine.PoolByDefault) { Coroutine result = null; UObject ownerObj = obj as UObject; if (ownerObj != null) { IntPtr world = Native_UObject.GetWorld(ownerObj.Address); Debug.Assert(world != IntPtr.Zero, "UObject coroutines must be objects with a UWorld reference (e.g. AActor) - " + "this is so that the coroutine can be stopped when the world is destroyed."); } // Let the caller do this check /*if (!FThreading.IsInGameThread()) * { * FThreading.RunOnGameThread(delegate () { result = StartCoroutine(obj, coroutine, group, tag, pool); }); * return result; * }*/ if (pool) { result = CoroutinePool.New(coroutine); } else { result = new Coroutine(coroutine); } result.Owner = obj; result.Group = group; result.mainCollectionIndex = coroutines.Count; result.Tag = tag; coroutines.Add(result); if (ownerObj != null) { List <Coroutine> collection; if (!coroutinesByObject.TryGetValue(ownerObj, out collection)) { coroutinesByObject.Add(ownerObj, collection = new List <Coroutine>()); } result.objectsCollectionIndex = collection.Count; collection.Add(result); } if (!string.IsNullOrEmpty(tag)) { List <Coroutine> collection; if (!coroutinesByTag.TryGetValue(tag, out collection)) { coroutinesByTag.Add(tag, collection = new List <Coroutine>()); } result.tagsCollectionIndex = collection.Count; collection.Add(result); } return(result); }
// If the number of active coroutines is under the limit specified in the constructor, run the // given coroutine. Otherwise, queue it to be run when other coroutines finish. // coroutine: Coroutine group to run or place in a queue public void Run(CoroutineGroup coroutineGroup) { // verify if number of running coroutine groups is less then max allowed number if (numActive < maxActive) { Debug.Log("Run " + coroutineGroup.CoroutineGroupID); // create new coroutine group runner var runner = CoroutineGroupRunner(coroutineGroup); // run new coroutine coroutineStarter(runner); } else { // verify if group is not already in a queue if (GetCoroutineGroupFromQueueByID(coroutineGroup.CoroutineGroupID) == null) { Debug.Log("Queued " + coroutineGroup.CoroutineGroupID); queue.Enqueue(coroutineGroup); } else { Debug.Log(coroutineGroup.CoroutineGroupID + " group is already in a queue"); } } }
private IEnumerator isFinishedEmpty_VerifyTrue() { CoroutineGroup coroutineGroup = new CoroutineGroup(); IntegrationTestEx.FailIf(!coroutineGroup.IsFinished); yield break; }
internal static void ProcessCoroutines(CoroutineGroup group) { runningGroup = group; insideMainCoroutineLoop = true; for (int i = coroutines.Count - 1; i >= 0; --i) { Coroutine coroutine = coroutines[i]; Debug.Assert(coroutine.mainCollectionIndex == i, "Coroutine main collection index is invalid"); if (coroutine.CurrentGroup == group && !coroutine.Complete) { coroutine.Process(group); } if (coroutine.Complete) { CoroutineRemoveAtSwap(coroutine, true); } } insideMainCoroutineLoop = false; // Do we need some kind of while loop here? If a coroutine has been processed here // and gets added to a different comparable collection it wont be processed until // the next frame even if it would be completed in this frame. Possibly return // a bool in Process if it an item was removed from the collection and keep running // this loop until all Process calls return false? for (int i = comparableCollections.Count - 1; i >= 0; --i) { IComparableYieldInstructionCollection collection = comparableCollections[i]; collection.Process(group); } runningGroup = CoroutineGroup.None; }
internal WaitForGroup PoolNew(CoroutineGroup group, ulong skipTicks, uint skipFrames) { hasWaitForTicks = false; hasWaitForFrames = false; Group = group; if (skipTicks > 0) { if (waitForTicks == null) { waitForTicks = new WaitForTicks(skipTicks); } else { waitForTicks.Ticks = skipTicks; } hasWaitForTicks = true; } if (skipFrames > 0) { if (waitForFrames == null) { waitForFrames = new WaitForFrames(skipFrames); } else { waitForFrames.Frames = skipFrames; } hasWaitForFrames = true; } return(this); }
private bool ProcessCurrentInstruction(CoroutineGroup group) { if (CurrentInstruction != null) { if (!ProcessInstruction(CurrentInstruction, group)) { return(false); } CurrentInstruction = null; } while (injectedInstructionQueue != null && injectedInstructionQueue.Count > 0) { CurrentInstruction = injectedInstructionQueue.Dequeue(); CurrentInstruction.Begin(); IsCurrentInstructionInjected = true; if (!ProcessInstruction(CurrentInstruction, group)) { return(false); } } IsCurrentInstructionInjected = false; return(true); }
private void addCoroutineToGroup(ICoroutine coroutine, CoroutineGroup group) { if (!coroutine.Disposed && !coroutine.Cancelled && !coroutine.Completed) { group.Add(coroutine); } }
private static Invoker StartInvoker(object obj, InvokerHandlerType handlerType, Delegate handler, InvokerType type, ulong value, ulong repeatValue, CoroutineGroup group = CoroutineGroup.Tick, bool pool = PoolByDefault) { IntPtr world = IntPtr.Zero; UObject ownerObj = obj as UObject; if (ownerObj != null) { world = Native_UObject.GetWorld(ownerObj.Address); Debug.Assert(world != IntPtr.Zero, "UObject invokers must be objects with a UWorld reference (e.g. AActor) - " + "this is so that the invoker can be stopped when the world is destroyed."); } Invoker invoker = pool ? InvokerPool.GetObject() : new Invoker(); invoker.OwnerWorld = world; invoker.Owner = obj; invoker.SetHandler(handlerType, handler); switch (type) { case InvokerType.Delay: TimeSpan time = TimeSpan.FromTicks((long)value); TimeSpan repeatTime = TimeSpan.FromTicks((long)repeatValue); if (repeatTime != default(TimeSpan)) { invoker.SetTime(time, repeatTime); } else { invoker.SetTime(time); } break; case InvokerType.Ticks: if (repeatValue != default(ulong)) { invoker.SetTicks(value, repeatValue); } else { invoker.SetTicks(value); } break; case InvokerType.Frames: if (repeatValue != default(ulong)) { invoker.SetFrames(value, repeatValue); } else { invoker.SetFrames(value); } break; } invoker.SetGroup(group); invoker.Start(); return(invoker); }
private IEnumerator isFinished_VerifyFalse() { CoroutineGroup coroutineGroup = new CoroutineGroup(); coroutineGroup.StartAndAdd(testerCoroutine(), this, "testerCoroutineEmptyEnumator"); IntegrationTestEx.FailIf(coroutineGroup.IsFinished); yield break; }
private IEnumerator isFinished_VerifyTrue() { CoroutineGroup group = new CoroutineGroup(); yield return(group.StartAndAdd(testerCoroutine(), this, "testerCoroutineEmptyEnumator")); IntegrationTestEx.FailIf(!group.IsFinished); }
void OnEnable() { mCoroutineGroup = CoroutineHelper.Factory.CreateCoroutineGroup(); for (int i = 0; i < 20; i++) { mCoroutineGroup.StartCoroutine(Foo()); } }
private bool ProcessInstruction(YieldInstruction instruction, CoroutineGroup group) { if (CurrentGroup != group || instruction.KeepWaiting) { return(false); } instruction.End(); ReleaseInstruction(instruction); return(true); }
// Create the queue, initially with no coroutine groups // maxActive: // Maximum number of coroutines to run at once. This must be at least one. // coroutineStarter: // Delegate to start coroutines with. Normally you'd pass // MonoBehaviour.StartCoroutinefor this. // Exception ArgumentException if maxActive is zero. public CoroutineGroupQueue(uint maxActive, Func <IEnumerator, Coroutine> coroutineStarter) { if (maxActive == 0) { throw new ArgumentException("Must be at least one", "maxActive"); } this.maxActive = maxActive; this.coroutineStarter = coroutineStarter; queue = new Queue <CoroutineGroup>(); runningCoroutineGroup = null; }
private void OnGroupChanged(T instruction, CoroutineGroup oldGroup, CoroutineGroup newGroup) { UnrealBinaryHeapEx <T> oldCollection = GetCollection(oldGroup); UnrealBinaryHeapEx <T> newCollection = GetCollection(newGroup); if (oldCollection != null && newCollection != null && oldCollection != newCollection) { oldCollection.HeapRemove(instruction); newCollection.HeapPush(instruction); } }
private static InvokerCollectionGroup GetInvokerGroup(CoroutineGroup group) { switch (group) { case CoroutineGroup.Tick: return(tickInvokers); case CoroutineGroup.BeginFrame: return(beginFrameInvokers); case CoroutineGroup.EndFrame: return(endFrameInvokers); } return(null); }
public void Process(CoroutineGroup group) { if (IsPaused) { return; } if (!ProcessCurrentInstruction(group)) { return; } if (Enumerator == null) { FMessage.Log(ELogVerbosity.Error, "Coroutine enumerator is null"); Stop(); return; } try { while (Enumerator.MoveNext()) { object current = Enumerator.Current; YieldInstruction instruction = current as YieldInstruction; if (instruction != null) { CurrentInstruction = instruction; CurrentInstruction.Owner = this; CurrentInstruction.Begin(); if (!ProcessCurrentInstruction(group)) { return; } } else { return; } } } catch (Exception e) { FMessage.Log(ELogVerbosity.Error, "Exception when running coroutine. " + Environment.NewLine + e.ToString()); Stop(); return; } Complete = true; }
private IEnumerator loadIconsForTubeDefinition(TubeDefinition tubeDefinition) { CoroutineGroup coroutineGroup = new CoroutineGroup(); addCoroutineToGroup(CoroutineRunner.Start(loadIcon(0, tubeDefinition.ButtonIconKeyDisabled.Key), this, ""), coroutineGroup); addCoroutineToGroup(CoroutineRunner.Start(loadIcon(1, tubeDefinition.ButtonIconKeyOff.Key), this, ""), coroutineGroup); addCoroutineToGroup(CoroutineRunner.Start(loadIcon(2, tubeDefinition.ButtonIconKeyOn.Key), this, ""), coroutineGroup); addCoroutineToGroup(CoroutineRunner.Start(loadIcon(3, tubeDefinition.ButtonIconKeyOn.Key), this, ""), coroutineGroup); while (!coroutineGroup.IsFinished) { yield return(null); } coroutineGroup.Clear(); trayInputButton.Icon.sprite = trayInputButton.IconSprite.Sprites[(int)trayInputButton.CurrentViewState]; }
public WaitForGroup(CoroutineGroup group, ulong skipTicks = 0, uint skipFrames = 0) { Group = group; if (skipTicks > 0) { waitForTicks = new WaitForTicks(skipTicks); hasWaitForTicks = true; } if (skipFrames > 0) { waitForFrames = new WaitForFrames(skipFrames); hasWaitForFrames = true; } }
private UnrealBinaryHeapEx <T> GetCollection(CoroutineGroup group) { switch (group) { case CoroutineGroup.Tick: return(tick); case CoroutineGroup.BeginFrame: return(beginFrame); case CoroutineGroup.EndFrame: return(endFrame); default: return(null); } }
private static Invoker StartInvoker(object obj, InvokerHandlerType handlerType, Delegate handler, InvokerType type, ulong value, ulong repeatValue, CoroutineGroup group = CoroutineGroup.Tick, bool pool = PoolByDefault) { Invoker invoker = pool ? InvokerPool.GetObject() : new Invoker(); invoker.SetHandler(handlerType, handler); switch (type) { case InvokerType.Delay: TimeSpan time = TimeSpan.FromTicks((long)value); TimeSpan repeatTime = TimeSpan.FromTicks((long)repeatValue); if (repeatTime != default(TimeSpan)) { invoker.SetTime(time, repeatTime); } else { invoker.SetTime(time); } break; case InvokerType.Ticks: if (repeatValue != default(ulong)) { invoker.SetTicks(value, repeatValue); } else { invoker.SetTicks(value); } break; case InvokerType.Frames: if (repeatValue != default(ulong)) { invoker.SetFrames(value, repeatValue); } else { invoker.SetFrames(value); } break; } invoker.SetGroup(group); invoker.Start(); return(invoker); }
public void Process(CoroutineGroup group) { UnrealBinaryHeapEx <T> collection = GetCollection(group); while (collection.Count > 0) { T instruction = collection.HeapTop(); if (instruction.KeepWaiting) { return; } collection.HeapPopDiscard(); // Return the control over to the main coroutines collection instruction.comparableCollection = null; Coroutine.ComparableEnd(instruction.Owner); } }
private IEnumerator loadWidgets(List <CellPhoneActivityDefinition> widgetDatas) { CoroutineGroup coroutineGroup = new CoroutineGroup(); Dictionary <CellPhoneActivityDefinition, GameObject> widgetDataToPrefab = new Dictionary <CellPhoneActivityDefinition, GameObject>(); for (int i = 0; i < widgetDatas.Count; i++) { ICoroutine coroutine = CoroutineRunner.Start(loadWidget(widgetDatas[i], widgetDataToPrefab), this, "loadWidget"); if (!coroutine.Disposed && !coroutine.Cancelled && !coroutine.Completed) { coroutineGroup.Add(coroutine); } } while (!coroutineGroup.IsFinished) { yield return(null); } instantiateWidgets(widgetDatas, widgetDataToPrefab); }
private IEnumerator clear_VerifyDidNotCancel() { CoroutineGroup group = new CoroutineGroup(); bool testerDidFinish = false; bool testerDidCancel = false; ICoroutine coroutine = group.StartAndAdd(testerCoroutine(), this, "testerCoroutine"); coroutine.ECompleted += delegate { testerDidFinish = true; }; coroutine.ECancelled += delegate { testerDidCancel = true; }; group.Clear(); yield return(coroutine); IntegrationTestEx.FailIf(testerDidCancel); IntegrationTestEx.FailIf(!testerDidFinish); }
public CoroutineGroup GetCoroutineGroupByID(string coroutineGroupID) { // verify if coroutine group ID is empty if (coroutineGroupID == null) { // create new random group id coroutineGroupID = Guid.NewGuid().ToString(); // create and return new coroutine group return(new CoroutineGroup(coroutineGroupID, coroutineStarter)); } else { // verify if running coroutine group is not null if (runningCoroutineGroup != null) { // verify if this not already running coroutin group // Note running coroutine group is already removed from queue, so you will not be able to find it there if (runningCoroutineGroup.CoroutineGroupID == coroutineGroupID) { // return reference to the running coroutine group return(runningCoroutineGroup); } } // if we are still here.. // try to get coroutine group by its ID from a queue CoroutineGroup coroutineGroup = GetCoroutineGroupFromQueueByID(coroutineGroupID); // verify if coroutine group is null if (coroutineGroup == null) { // create new coroutine group with defined ID return(new CoroutineGroup(coroutineGroupID, coroutineStarter)); } else { // return reference to existing coroutine group from queue return(coroutineGroup); } } }
// Run corotine with defined or not defined group ID public void Run(IEnumerator coroutine, string coroutineGroupID = null) { if (coroutineGroupID != null) { Debug.Log("Running " + coroutine.ToString() + " coroutine with " + coroutineGroupID + " group ID"); } else { Debug.Log("Running " + coroutine.ToString() + " coroutine "); } // init coroutineGroup variable CoroutineGroup coroutineGroup = GetCoroutineGroupByID(coroutineGroupID); // add coroutine to the group coroutineGroup.Add(coroutine); // verify if coroutine group is not already running if (!coroutineGroup.IsRunning) { // try to run Coroutine group Run(coroutineGroup); } }
private IEnumerator startAndAddMultiple_VerifyDidComplete() { CoroutineGroup group = new CoroutineGroup(); bool tester1DidFinish = false; bool tester1DidCancel = false; bool tester2DidFinish = false; bool tester2DidCancel = false; ICoroutine coroutine1 = group.StartAndAdd(testerCoroutine(), this, "testerCoroutine1"); ICoroutine coroutine2 = group.StartAndAdd(testerCoroutine(), this, "testerCoroutine2"); coroutine1.ECompleted += delegate { tester1DidFinish = true; }; coroutine1.ECancelled += delegate { tester1DidCancel = true; }; coroutine2.ECompleted += delegate { tester2DidFinish = true; }; coroutine2.ECancelled += delegate { tester2DidCancel = true; }; IntegrationTestEx.FailIf(!group.Contains(coroutine1)); IntegrationTestEx.FailIf(!group.Contains(coroutine2)); while (!group.IsFinished) { yield return(null); } IntegrationTestEx.FailIf(!tester1DidFinish); IntegrationTestEx.FailIf(tester1DidCancel); IntegrationTestEx.FailIf(!tester2DidFinish); IntegrationTestEx.FailIf(tester2DidCancel); IntegrationTestEx.FailIf(group.Contains(coroutine1)); IntegrationTestEx.FailIf(group.Contains(coroutine2)); }
private IEnumerator add_VerifyDoesContainAndDidFinish() { CoroutineGroup group = new CoroutineGroup(); bool testerDidFinish = false; bool testerDidCancel = false; ICoroutine coroutine = CoroutineRunner.Start(testerCoroutine(), this, "testerCoroutine"); coroutine.ECompleted += delegate { testerDidFinish = true; }; coroutine.ECancelled += delegate { testerDidCancel = true; }; IntegrationTestEx.FailIf(group.Contains(coroutine)); group.Add(coroutine); IntegrationTestEx.FailIf(!group.Contains(coroutine)); yield return(coroutine); IntegrationTestEx.FailIf(group.Contains(coroutine)); IntegrationTestEx.FailIf(!testerDidFinish); IntegrationTestEx.FailIf(testerDidCancel); }
private IEnumerator remove_VerifyDoesNotContain() { CoroutineGroup group = new CoroutineGroup(); bool testerDidFinish = false; bool testerDidCancel = false; ICoroutine coroutine = group.StartAndAdd(testerCoroutine(), this, "testerCoroutine"); coroutine.ECompleted += delegate { testerDidFinish = true; }; coroutine.ECancelled += delegate { testerDidCancel = true; }; IntegrationTestEx.FailIf(!group.Contains(coroutine)); group.Remove(coroutine); IntegrationTestEx.FailIf(group.Contains(coroutine)); yield return(coroutine); IntegrationTestEx.FailIf(!testerDidFinish); IntegrationTestEx.FailIf(testerDidCancel); IntegrationTestEx.FailIf(group.Contains(coroutine)); }