示例#1
0
        public void Execute(Coroutine coroutine)
        {
            coroutine.SignalStarted(this, executionState, null);
            var ev = new StartCoroutineEvent(coroutine);

            eventQueue.Enqueue(ev);
        }
示例#2
0
        public void ExecuteImmediately(Coroutine coroutine)
        {
            if (updateThreadID == -1)
            {
                throw new CoroutineException("ExecuteImmediatelly not called from coroutine");
            }

            if (updateThreadID != Thread.CurrentThread.ManagedThreadId)
            {
                throw new CoroutineException("ExecuteImmediatelly called from different scheduler than current coroutine");
            }

            coroutine.SignalStarted(this, executionState, null);
            StartAndMakeFirstIteration(coroutine);
        }
示例#3
0
        private void StartSubCoroutine(Coroutine newWaitCoroutine, Coroutine spawner)
        {
            var internalState = CreateCoroutineState(newWaitCoroutine);

            newWaitCoroutine.SignalStarted(this, executionState, spawner);

            // We want to do evaluation to the first yield immediatelly
            var advanceAction = AdvanceCoroutine(internalState);

            switch (advanceAction)
            {
            case AdvanceAction.Keep:
                executingCoroutines.AddFirst(internalState);
                break;

            case AdvanceAction.MoveToWaitForTrigger:
                break;

            case AdvanceAction.Complete:
                break;
            }
        }
示例#4
0
        private bool AdvanceCoroutine(long coroutineID, Coroutine coroutine, IEnumerator <IWaitObject> iterator)
        {
            while (true)
            {
                // Execute the coroutine's next frame
                bool isCompleted;

                // We need to lock to ensure cancellation from source does not interfere with frame
                lock (coroutine.SyncRoot)
                {
                    // Cancellation can come from outside, as well as completion
                    if (coroutine.IsComplete)
                    {
                        return(true);
                    }

                    try
                    {
                        isCompleted = !iterator.MoveNext();
                    }
                    catch (Exception ex)
                    {
                        coroutine.SignalException(ex);
                        return(true);
                    }

                    if (isCompleted)
                    {
                        coroutine.SignalComplete(false, null);
                        return(true);
                    }
                }

                IWaitObject newWait = iterator.Current;

                // Special case null means wait to next frame
                if (newWait is WaitForSeconds waitForSeconds)
                {
                    timerTrigger.AddTrigger(waitForSeconds.WaitTime, new ContinueCoroutineEvent(coroutineID));
                    return(false);
                }

                // Special case null means wait to next frame
                if (newWait == null)
                {
                    eventQueue.EnqueueNextFrame(new ContinueCoroutineEvent(coroutineID));
                    return(false);
                }
                else if (newWait is ReturnValue retVal)
                {
                    coroutine.SignalComplete(true, retVal.Result);
                    return(true);
                }

                if (newWait is Coroutine newWaitCoroutine)
                {
                    // If we yield an unstarted coroutine, we add it to this scheduler!
                    if (newWaitCoroutine.Status == CoroutineStatus.WaitingForStart)
                    {
                        coroutine.SignalStarted(this, executionState, coroutine);
                        StartAndMakeFirstIteration(newWaitCoroutine);

                        switch (newWaitCoroutine.Status)
                        {
                        case CoroutineStatus.CompletedWithException:
                            coroutine.SignalException(newWaitCoroutine.Exception);
                            return(true);

                        case CoroutineStatus.Cancelled:
                            coroutine.SignalException(new OperationCanceledException("Internal coroutine was cancelled"));
                            return(true);
                        }
                    }
                }

                if (newWait.IsComplete)
                {
                    // If the wait object is complete, we continue immediatelly (yield does not split frames)
                    continue;
                }

                // Check if we get notified for completion, otherwise polling is used
                if (newWait is IWaitObjectWithNotifyCompletion withCompletion)
                {
                    withCompletion.RegisterCompleteSignal(
                        () =>
                    {
                        eventQueue.Enqueue(new ContinueCoroutineEvent(coroutineID));
                    });
                }

                return(false);
            }
        }