/// <summary> /// Ticks all living coroutines, advancing time by the specified amount. /// </summary> /// <param name="elapsed">The time that has elapsed since the previous tick.</param> /// <returns>Whether any threads are still alive.</returns> public bool Tick(TimeSpan elapsed) { if (elapsed.Ticks < 0) { throw new ArgumentOutOfRangeException(nameof(elapsed)); } if (_executingThread != null) { throw new InvalidOperationException("Recursive ticking not allowed"); } _time += elapsed; for (int i = 0; i < _threads.Count; i++) { CoroutineThread thread = _threads[i]; _executingThread = thread; try { thread.Tick(elapsed); } finally { _executingThread = null; } } return(_threads.Count != 0); }
internal void Tick(TimeSpan elapsed) { CoroutineThread oldCurrent = t_currentThread; t_currentThread = this; _elapsedTime = elapsed; try { bool endLoop = false; while (!endLoop) { IEnumerable next = null; FrameResult frameResult = RunFrame(_stack.Peek(), ref next); switch (frameResult) { case FrameResult.Yield: endLoop = true; break; case FrameResult.Pop: IEnumerator oldTop = _stack.Pop(); (oldTop as IDisposable)?.Dispose(); if (_stack.Count == 0) { Dispose(); endLoop = true; } break; case FrameResult.Push: _stack.Push(next.GetEnumerator()); break; default: throw new ArgumentOutOfRangeException(); } } } catch (Exception ex) { Dispose(ex); throw; } finally { Debug.Assert(!_hasResult); t_currentThread = oldCurrent; } }
/// <summary> /// Executes a coroutine in a new thread. /// </summary> /// <param name="cor">An enumerable object that can provide a coroutine.</param> public CoroutineThread Start(IEnumerable cor) { if (cor == null) { throw new ArgumentNullException(nameof(cor)); } var thread = new CoroutineThread(this, cor); _threads.Add(thread); return(thread); }
internal void OnThreadDisposed(CoroutineThread thread) { _threads.Remove(thread); }
/// <summary> /// Gets the next coroutine to be pushed onto the thread's stack. If null, yield until the next tick. /// </summary> /// <param name="thread">The current thread.</param> /// <param name="cor">A coroutine to push if the behavior is Push.</param> /// <returns>The behavior of the action.</returns> public abstract CoroutineActionBehavior Process(CoroutineThread thread, ref IEnumerable cor);
// ReSharper disable once RedundantAssignment public override CoroutineActionBehavior Process(CoroutineThread thread, ref IEnumerable cor) { cor = thread.Executor.Parallel(_enumerables); _enumerables = null; return(CoroutineActionBehavior.Push); }
// ReSharper disable once RedundantAssignment public override CoroutineActionBehavior Process(CoroutineThread thread, ref IEnumerable cor) { cor = thread.Executor.Delay(_time); _time = default(TimeSpan); return(CoroutineActionBehavior.Push); }
public override CoroutineActionBehavior Process(CoroutineThread thread, ref IEnumerable cor) { thread.SetResult(_value); _value = null; return(CoroutineActionBehavior.Pop); }