Пример #1
0
        /// Return value indicate whether this coroutine is dead.
        internal bool _Update(float fTime)
        {
            bool bIsDead = false;

            try
            {
                if (_onUpdate != null && state == CoroutineState.Running)
                {
                    _onUpdate(_pCurrentInstruction);
                }
            }
            catch (Exception e)
            {
                _HandleException(new CoroutineException(e, this));
                bIsDead = true;
            }

            bool bIsComplete = false;

            if (_state < CoroutineState.Running)
            {
                if (_state == CoroutineState.Paused)
                {
                    return(false);
                }
                else if (_state == CoroutineState.Stopped)
                {
                    bIsComplete = true;
                }
                else if (_state == CoroutineState.Disposed)
                {
                    /// Occurred when a manual coroutine is Removed.
                    return(true);
                }
                else
                {
                    Debugger.Assert(false);
                }
            }

            try
            {
                _pCoroutineMgr._CoEnterLogStack.Push(this);

                if (bIsComplete)
                {
                    if (!__bIsManualStopped)
                    {
                        __doComplete();
                    }
                    return(true);
                }

                ///-------------------
                bIsDead = false;

                Debugger.Assert(_pCurrentInstruction != null);

                Debugger.DebugSection(() =>
                {
                    if (_pCurrentInstruction.GetInstructionType() == YieldInstructionType.Coroutine)
                    {
                        var coroutine = _pCurrentInstruction as Coroutine;
                        Debugger.ConditionalAssert(coroutine._bPooled, coroutine.state != CoroutineState.Freed);
                    }
                });

                if (_pCurrentInstruction.GetInstructionType() == YieldInstructionType.ReturnValue)
                {
                    bIsDead = true;

                    _ReturnValue pReturnValue = _pCurrentInstruction as _ReturnValue;

                    __doComplete(pReturnValue.returnValue);
                }
                else
                {
                    _pCurrentInstruction.Update(fTime);

                    if (_pCurrentInstruction.IsDone())
                    {
                        if (_onYieldDone != null)
                        {
                            _onYieldDone(_pCurrentInstruction);
                        }

                        if (state != CoroutineState.Stopped)
                        {
                            Debugger.Assert(_pCurrentInstruction != null);
                            _pCurrentInstruction.Stop();

                            if (!_pCoroutineFunc.MoveNext())
                            {
                                _pCurrentInstruction.DecRef();
                                _pCurrentInstruction = null;

                                bIsDead = true;
                                __doComplete();
                            }
                            else
                            {
                                if (_state != CoroutineState.Stopped)
                                {
                                    Debugger.Assert(_state != CoroutineState.Freed && _state != CoroutineState.Disposed);
                                    Debugger.Assert(_pCoroutineFunc != null, "Coroutine function is null but still in update, you may be operated on a dead coroutine!!!");

                                    /// Why defRef here? Because MoveNext() may cause current instruction
                                    _pCurrentInstruction.DecRef();

                                    _pCurrentInstruction = _pCoroutineFunc.Current as IYieldInstruction;
                                    if (_pCurrentInstruction == null)
                                    {
                                        throw new UnsupportedYieldInstruction();
                                    }

                                    _pCurrentInstruction.Start(fTime);
                                    _pCurrentInstruction.IncRef();
                                }
                            }
                        }
                    }
                }
            }
            catch (Exception e)
            {
                Debugger.Assert(!(e is CoroutineException));
                _HandleException(new CoroutineException(e, this));
                bIsDead = true;
            }
            finally
            {
                Debugger.Assert(_pCoroutineMgr._CoEnterLogStack.Peek() == this);
                _pCoroutineMgr._CoEnterLogStack.Pop();
            }

            return(bIsDead);
        }
Пример #2
0
        internal void _Start(IEnumerator pCoroutineFunc)
        {
            Debugger.Assert(GetRef() != 0);

            _Parent = _pCoroutineMgr.Current();
            if (_Parent != null)
            {
                _Parent._DoChildCoStart(this);
            }

            Debugger.Assert(_state != CoroutineState.Disposed);
            if (_state == CoroutineState.Running || _state == CoroutineState.Paused)
            {
                Stop();
            }

            try
            {
                _pCoroutineMgr._CoEnterLogStack.Push(this);

                if (!_bInQueue)
                {
                    CoroutineMgr._Instance._AddToQueue(this);
                }

                _pCoroutineFunc = pCoroutineFunc;

                if (_onStart != null)
                {
                    _onStart(this);
                }

                _state = CoroutineState.Running;

                if (_pCoroutineFunc.MoveNext())
                {
                    /// 如果子Coroutine的第一行代码抛出异常,_state会被设置为Stopped
                    if (_state != CoroutineState.Stopped)
                    {
                        Debugger.Assert(_state != CoroutineState.Disposed && _state != CoroutineState.Freed);

                        _pCurrentInstruction = _pCoroutineFunc.Current as IYieldInstruction;

                        if (_pCurrentInstruction == null)
                        {
                            throw new UnsupportedYieldInstruction();
                        }

                        _pCurrentInstruction.Start(scalable ? _pCoroutineMgr._Time : _pCoroutineMgr._RealTime);
                        _pCurrentInstruction.IncRef();
                    }
                }
                else
                {
                    /// When coroutine has the 'yield break' at first line, will reach here.
                    /// The onStop will be called at next _Update.
                    _state = CoroutineState.Stopped;
                }
            }
            catch (Exception e)
            {
                if (e is CoroutineException)
                {
                    _HandleException(e as CoroutineException);
                }
                else
                {
                    _HandleException(new CoroutineException(e, this));
                }
            }
            finally
            {
                Debugger.Assert(_pCoroutineMgr._CoEnterLogStack.Peek() == this);
                _pCoroutineMgr._CoEnterLogStack.Pop();
            }
        }