public void InsertRoutine(FECgCoroutineSchedule schedule, FCgRoutine pivot, FCgRoutine insert) { // Detach insert // insert is the Tail if (insert.Next == null) { Tails[schedule] = insert.Prev; } else { insert.Next.Prev = insert.Prev; } insert.Prev.Next = insert.Next; // Insert insert ahead of pivot // pivot is the Head if (pivot.Prev == null) { Heads[schedule] = insert; pivot.Prev = insert; insert.Next = pivot; insert.Prev = null; } else { pivot.Prev.Next = insert; insert.Prev = pivot.Prev; insert.Next = pivot; pivot.Prev = insert; } }
public void Reset() { Prev = null; Next = null; State = ECgRoutineState.Free; Fiber = null; Name = ""; RoutineType = INVALID_TYPE; WaitingFor = null; Blocking = null; Parent = null; Children.Clear(); Owner.UnSet(); OwnerName = ""; StopCondition.Clear(); StopMessages.Clear(); for (byte i = 0; i < (byte)ECgCoroutineMessage.MAX; ++i) { Messages_Recieved[(ECgCoroutineMessage)i].Clear(); } Add.Unbind(); Remove.Unbind(); StartTime = 0.0f; ElapsedTime = 0.0f; DeltaTime = 0.0f; TickCount = 0; Delay = 0.0f; bWaitForFrame = false; WaitForFrameCounter = 0; WaitForFrame = 0; WaitForFrameType = null; bWaitForTime = false; WaitForTimeTimer = 0.0f; WaitForTime = 0.0f; WaitForTimeType = null; bWaitForFlag = false; WaitForBoolType = null; WaitForFlagType = null; bWaitForListenMessage = false; WaitForListenMessage = INVALID_LISTEN_MESSAGE; WaitForListenMessageType = null; EndReason = ECgCoroutineEndReason.MAX; for (byte i = 0; i < INT_SIZE; ++i) { Ints[i] = 0; } for (byte i = 0; i < FLOAT_SIZE; ++i) { Floats[i] = 0.0f; } }
public void Prep(FCgRoutine r, FCgCoroutinePayload payload) { r.Start(payload.Fiber, payload.Stop, payload.Owner, payload.OwnerName, payload.StartTime, payload.Add, payload.Remove, payload.RoutineType); r.State = ECgRoutineState.Allocating; LogTransaction(ECgCoroutineSchedulerCached.Str.Prep, ECgCoroutineTransaction.Allocate, r); payload.Reset(); }
public static bool CoroutineStopCondition_CheckMonoObject(FCgRoutine r) { MonoBehaviour mb = r.Owner.Get <MonoBehaviour>(); if (mb != null) { return(true); } return(false); }
public FCgRoutine Allocate(FCgCoroutinePayload payload) { FECgCoroutineSchedule schedule = payload.Schedule; FCgRoutine r = Allocate_Internal(schedule); r.Start(payload.Fiber, payload.Stop, payload.Owner, payload.OwnerName, payload.StartTime, payload.Add, payload.Remove, payload.RoutineType); r.State = ECgRoutineState.Allocating; LogTransaction(ECgCoroutineSchedulerCached.Str.Allocate, ECgCoroutineTransaction.Allocate, r); payload.Reset(); return(r); }
public void BroadcastMessage(FECgCoroutineSchedule schedule, ECgCoroutineMessage msgType, string msg, object owner = null) { int count = RoutinesRunning[schedule].Count; for (int i = 0; i < count; ++i) { FCgRoutine r = RoutinesRunning[schedule][i]; if (owner != null && owner != r.Owner.Get()) { continue; } r.ReceiveMessage(msgType, msg); } }
private FCgRoutine Allocate_Internal(FECgCoroutineSchedule schedule) { for (ushort i = 0; i < POOL_SIZE; ++i) { PoolIndicies[schedule] = (PoolIndicies[schedule] + 1) % POOL_SIZE; FCgRoutine r = Pools[schedule][PoolIndicies[schedule]]; if (r.State != ECgRoutineState.Free) { continue; } return(r); } Debug.LogError("FCgRoutine.Allocate: No free Routines. Pools[" + schedule.ToString() + "] is exhausted. Look for runaway Coroutines or consider raising the pool size."); return(null); }
public FCgRoutine Start(FCgCoroutinePayload payload) { FECgCoroutineSchedule schedule = payload.Schedule; FCgRoutine r = Allocate_Internal(schedule); if (r == null) { payload.Reset(); return(null); } // If NO Head, Make r the Head if (Heads[schedule] == null) { Heads[schedule] = r; Tails[schedule] = r; } // Add r end of the list, Make r the Tail else { FCgRoutine tail = Tails[schedule]; tail.Next = r; r.Prev = tail; Tails[schedule] = r; } RoutinesRunning[schedule].Add(r); // TODO: get Time from Manager_Time r.Start(payload.Fiber, payload.Stop, payload.Owner, payload.OwnerName, payload.StartTime, payload.Add, payload.Remove, payload.RoutineType); r.State = ECgRoutineState.Running; LogTransaction(ECgCoroutineSchedulerCached.Str.Start, ECgCoroutineTransaction.Start, r); payload.Reset(); r.Run(0.0f); return(r); }
public FCgRoutine Start(FECgCoroutineSchedule schedule, FCgRoutine r) { // If NO Head, Make r the Head if (Heads[schedule] == null) { Heads[schedule] = r; Tails[schedule] = r; } // Add r end of the list, Make r the Tail else { FCgRoutine tail = Tails[schedule]; tail.Next = r; r.Prev = tail; Tails[schedule] = r; } RoutinesRunning[schedule].Add(r); r.State = ECgRoutineState.Running; r.Run(0.0f); return(r); }
public void Run(float deltaTime) { // Check Stop Messages int count = Messages_Recieved[ECgCoroutineMessage.Stop].Count; for (int i = 0; i < count; ++i) { if (StopMessages.FindIndex(s => s == Messages_Recieved[ECgCoroutineMessage.Stop][i]) != CgTypes.INDEX_NONE) { StopMessages.Clear(); End(ECgCoroutineEndReason.StopMessage); break; } } Messages_Recieved[ECgCoroutineMessage.Stop].Clear(); if (State == ECgRoutineState.End) { return; } // Check Stop Condition if (StopCondition.Broadcast(this)) { End(ECgCoroutineEndReason.StopCondition); } if (State == ECgRoutineState.End) { return; } DeltaTime = deltaTime; ElapsedTime += deltaTime; ++TickCount; bool move = true; // Check WaitForFrame if (bWaitForFrame) { if (WaitForFrameType != null) { WaitForFrame = WaitForFrameType.Get(); if (WaitForFrame < 0) { WaitForFrame = 0; WaitForFrameType = null; Debug.LogWarning("FCgRoutine.Run: yield return value of type 'FCgRoutine.FFrameType' is used for WaitForFrame. yield return value must be >= 0."); } } ++WaitForFrameCounter; move = WaitForFrameCounter >= WaitForFrame; if (move) { WaitForFrame = 0; bWaitForFrame = false; WaitForFrameCounter = 0; } } // Check WaitForTime if (bWaitForTime) { if (WaitForTimeType != null) { WaitForTime = WaitForTimeType.Get(); if (WaitForTime < 0.0f) { WaitForTime = 0.0f; WaitForTimeType = null; Debug.LogWarning("FCgRoutine.Run: yield return value of type 'FCgRoutine.FTimeType' is used for WaitForTime. yield return value must be >= 0.0f."); } } WaitForTimeTimer += deltaTime; move = WaitForTimeTimer >= WaitForTime; if (move) { WaitForTime = 0; bWaitForTime = false; WaitForTimeTimer = 0.0f; } } // Check WaitingFor if (bWaitingFor) { move = WaitingFor.State != ECgRoutineState.Running; if (move) { WaitingFor.Blocking = null; WaitingFor = null; bWaitingFor = false; } } // Check WaitForFlag if (bWaitForFlag) { move = (WaitForBoolType != null && WaitForBoolType.Get()) || (WaitForFlagType != null && WaitForFlagType.IsEqual()); if (WaitForBoolType != null) { } if (move) { WaitForBoolType = null; bWaitForFlag = false; } } // WaitForListenMessage if (bWaitForListenMessage) { // TODO: Need to overload != operator correctly if (!object.ReferenceEquals(WaitForListenMessageType, null)) { WaitForListenMessage = WaitForListenMessageType.Get(); if (WaitForListenMessage == INVALID_LISTEN_MESSAGE) { Debug.LogWarning("FCgRoutine.Run: yield return value of type 'FCgRoutine.FListenMessageType' is used for WaitForListenMessage. yield return value must NOT be empty."); } } move = WaitForListenMessage == INVALID_LISTEN_MESSAGE;// || if (move) { WaitForListenMessage = INVALID_LISTEN_MESSAGE; bWaitForListenMessage = false; } } if (!move) { return; } if (Fiber.MoveNext()) { object yieldCommand = Fiber.Current == null ? (object)1 : Fiber.Current; Type type = yieldCommand.GetType(); // WaitForFrame if (type == typeof(int)) { WaitForFrame = (int)yieldCommand; if (WaitForFrame < 0) { WaitForFrame = 0; Debug.LogWarning("FCgRoutine.Run: yield return value of type 'int' is used for WaitForFrame. yield return value must be >= 0."); } else { bWaitForFrame = true; WaitForFrameCounter = 0; } } else if (type == typeof(FFrameType)) { WaitForFrameType = (FFrameType)yieldCommand; if (WaitForFrameType.Get() < 0) { WaitForFrameType = null; Debug.LogWarning("FCgRoutine.Run: yield return value of type 'FCgRoutine.FFrameType' is used for WaitForFrame. yield return value must be >= 0."); } else { bWaitForFrame = true; WaitForFrameCounter = 0; } } // WaitForTime else if (type == typeof(float)) { WaitForTime = (float)yieldCommand; if (WaitForTime < 0.0f) { WaitForTime = 0.0f; Debug.LogWarning("FCgRoutine.Run: yield return value of type 'float' is used for WaitForTime. yield return value must be >= 0.0f."); } else { bWaitForTime = true; WaitForTimeTimer = 0.0f; } } else if (type == typeof(FTimeType)) { WaitForTimeType = (FTimeType)yieldCommand; if (WaitForTimeType.Get() < 0.0f) { WaitForTimeType = null; Debug.LogWarning("FCgRoutine.Run: yield return value of type 'FCgRoutine.FTimeType' is used for WaitForTime. yield return value must be >= 0.0f."); } else { bWaitForTime = true; WaitForTimeTimer = 0.0f; } } // WaitingFor else if (type == typeof(FCgRoutine)) { WaitingFor = (FCgRoutine)yieldCommand; WaitingFor.Blocking = this; bWaitingFor = true; // Fix linkage. Prev / Next InsertRoutine(Schedule, this, WaitingFor); } // WaitForFlag else if (type == typeof(FBoolType)) { WaitForBoolType = (FBoolType)yieldCommand; if (!WaitForBoolType.Get()) { bWaitForFlag = true; } } else if (typeof(ICgFlag).IsAssignableFrom(type)) { WaitForFlagType = (ICgFlag)yieldCommand; if (!WaitForFlagType.IsEqual()) { bWaitForFlag = true; } } // WaitForListenMessage else if (type == typeof(string)) { WaitForListenMessage = (string)yieldCommand; if (WaitForListenMessage == INVALID_LISTEN_MESSAGE) { Debug.LogWarning("FCgRoutine.Run: yield return value of type 'string' is used for WaitForListenMessage. yield return value must NOT be empty."); } else { bWaitForListenMessage = true; } } else if (type == typeof(FListenMessageType)) { WaitForListenMessageType = (FListenMessageType)yieldCommand; if (WaitForListenMessageType.Get() == INVALID_LISTEN_MESSAGE) { Debug.LogWarning("FCgRoutine.Run: yield return value of type 'string' is used for WaitForListenMessage. yield return value must NOT be empty."); } else { bWaitForListenMessage = true; } } // INVALID Type else { Debug.LogError("FCgRoutine.Run: Invalid Type: " + type.GetType() + " for yield. yield return value must be of type: int, FCgRoutine.FFrameType, float, FCgRoutine.FTimeType, FCgRoutine, FCgRoutine.FBoolType, ICgFlag, string, or FCgRoutine.FListenMessageType."); } } // Finished else { End(ECgCoroutineEndReason.EndOfExecution); } }
// Constructor public FCgRoutine(int index, FECgCoroutineSchedule schedule, InsertRoutineAheadOf insertRoutine) { Index = index; Schedule = schedule; Prev = null; Next = null; State = ECgRoutineState.Free; Fiber = null; Name = ""; RoutineType = INVALID_TYPE; bWaitingFor = false; WaitingFor = null; Blocking = null; InsertRoutine = insertRoutine; Parent = null; Children = new List <FCgRoutine>(); Owner = new FCgAttribute(); OwnerName = ""; StopCondition = new FCoroutineStopCondition(); StopMessages = new List <string>(); Messages_Recieved = new Dictionary <ECgCoroutineMessage, List <string> >(new ECgCoroutineMessageEqualityComparer()); for (byte i = 0; i < (byte)ECgCoroutineMessage.MAX; ++i) { Messages_Recieved[(ECgCoroutineMessage)i] = new List <string>(); } Add = new FAddRoutine(); Remove = new FRemoveRoutine(); StartTime = 0.0f; ElapsedTime = 0.0f; DeltaTime = 0.0f; TickCount = 0; Delay = 0.0f; bWaitForFrame = false; WaitForFrameCounter = 0; WaitForFrame = 0; WaitForFrameType = null; bWaitForTime = false; WaitForTime = 0.0f; WaitForTimeTimer = 0.0f; WaitForTimeType = null; bWaitForFlag = false; WaitForBoolType = null; WaitForFlagType = null; bWaitForListenMessage = false; WaitForListenMessage = INVALID_LISTEN_MESSAGE; WaitForListenMessageType = null; EndReason = ECgCoroutineEndReason.MAX; Ints = new int[INT_SIZE]; Floats = new float[FLOAT_SIZE]; }
public virtual bool RemoveRoutine(FCgRoutine r) { return(false); }
public virtual bool AddRoutine(FCgRoutine r) { return(false); }
public void LogTransaction(string functionName, ECgCoroutineTransaction transaction, FCgRoutine r) { if (!LogTransactions.Log()) { return; } string transactionAsString = transaction.ToString() + "ing (Reason=" + r.EndReason.ToString() + ")"; string schedule = r.Schedule.ToString(); float currentTime = Time.time; string elapsed = ""; if (transaction == ECgCoroutineTransaction.End) { float duration = currentTime - r.StartTime; elapsed = "Ran for " + r.TickCount + " Ticks and " + duration + " Seconds."; } if (r.Owner != null) { Debug.Log(functionName + ": On" + schedule + " " + transactionAsString + " Routine with Coroutine: " + r.Name + " at " + currentTime + ". Using Owner: " + r.OwnerName + ". " + elapsed); } else { Debug.Log(functionName + ": On" + schedule + " " + transactionAsString + " Routine with Coroutine: " + r.Name + " at " + currentTime + ". " + elapsed); } }
public void Update(FECgCoroutineSchedule schedule, float deltaTime) { // Iterate through List FCgRoutine current = Heads[schedule]; while (current != null) { if (current.State == ECgRoutineState.Running) { current.Run(deltaTime); } if (current.State == ECgRoutineState.End) { // Remove from List, Update Linkage. Prev / Next if (current.Prev != null) { current.Prev.Next = current.Next; if (current.Next != null) { current.Next.Prev = current.Prev; } // Update Tail else { Tails[schedule] = current.Prev; } } // Update Head else { if (current.Next != null) { current.Next.Prev = null; Heads[schedule] = current.Next; } // Last node in List else { Heads[schedule] = null; Tails[schedule] = null; } } LogTransaction("FCgRoutine.Update", ECgCoroutineTransaction.End, current); FCgRoutine r = current; current = current.Next; r.Reset(); } else { current = current.Next; } } // Check RoutinesRunning for any Routines that have Ended int count = RoutinesRunning[schedule].Count; for (int i = count - 1; i >= 0; --i) { FCgRoutine r = RoutinesRunning[schedule][i]; if (r.State == ECgRoutineState.Free) { RoutinesRunning[schedule].RemoveAt(i); } else if (r.State == ECgRoutineState.End) { if (r.EndReason == ECgCoroutineEndReason.EndOfExecution || r.EndReason == ECgCoroutineEndReason.Parent) { Debug.LogError("CgCoroutineSchedule.Update: Dangling Routine. Check iteration through List or if Routine was tampered with."); } r.Reset(); RoutinesRunning[schedule].RemoveAt(i); } } }