예제 #1
0
        /// <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);
        }
예제 #2
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;
            }
        }
예제 #3
0
        /// <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);
        }
예제 #4
0
 internal void OnThreadDisposed(CoroutineThread thread)
 {
     _threads.Remove(thread);
 }
예제 #5
0
 /// <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);
예제 #6
0
 // ReSharper disable once RedundantAssignment
 public override CoroutineActionBehavior Process(CoroutineThread thread, ref IEnumerable cor)
 {
     cor          = thread.Executor.Parallel(_enumerables);
     _enumerables = null;
     return(CoroutineActionBehavior.Push);
 }
예제 #7
0
 // ReSharper disable once RedundantAssignment
 public override CoroutineActionBehavior Process(CoroutineThread thread, ref IEnumerable cor)
 {
     cor   = thread.Executor.Delay(_time);
     _time = default(TimeSpan);
     return(CoroutineActionBehavior.Push);
 }
예제 #8
0
 public override CoroutineActionBehavior Process(CoroutineThread thread, ref IEnumerable cor)
 {
     thread.SetResult(_value);
     _value = null;
     return(CoroutineActionBehavior.Pop);
 }