internal void _HandleException(CoroutineException e) { if (_pCurrentInstruction != null) { _pCurrentInstruction.Stop(); _pCurrentInstruction.DecRef(); _pCurrentInstruction = null; } _pCoroutineFunc = null; _state = CoroutineState.Stopped; if (_onException != null) { _onException(this, e); } else { if (_Parent != null) { /// 'Throw up' to parent _Parent._HandleException(e); } else { CoroutineMgr._ThrowException(e); } } if (_onStopped != null) { _onStopped(this); _Parent = null; } }
private IEnumerator <IYieldInstruction> MockCoroutineOptionalYield(IYieldInstruction yieldInstruction, Func <bool> onStep) { while (onStep()) { yield return(yieldInstruction); } }
public bool MoveNext() { bool move = asyncInstruction.MoveNext(); yieldInstruction = asyncInstruction.Current == null ? NotWait.notWait : asyncInstruction.Current; return(move); }
private IEnumerator <IYieldInstruction> MockCoroutine(IYieldInstruction yieldInstruction, Hangout.Shared.Action onStep) { while (true) { yield return(yieldInstruction); onStep(); } }
public static IEnumerator RepeatFor(float time, Action <float> method, IYieldInstruction yieldInstruction) { var current = 0.0f; while (current < time) { yield return(yieldInstruction.Wait()); current += yieldInstruction.Increment(); method(Mathf.Clamp01(current / time)); } method(1.0f); }
///-------- private void __doComplete(object returnValue = null) { _pCoroutineFunc = null; if (_pCurrentInstruction != null) { _pCurrentInstruction.DecRef(); _pCurrentInstruction = null; } if (_onComplete != null) { _onComplete(this, returnValue); } _doStop(); }
override public void Stop() { Debugger.Assert(GetRef() != 0); Debugger.ConditionalAssert(_bPooled , !_AutoKill, "You can call pause/resume/stop a pooled coroutine only when AutoKill is false."); if (_state == CoroutineState.Stopped) { return; } __bIsManualStopped = true; _pCoroutineFunc = null; if (_pCurrentInstruction != null) { _pCurrentInstruction.Stop(); _pCurrentInstruction.DecRef(); _pCurrentInstruction = null; } _doStop(); }
override public bool IsDone() { bool bIsDone = false; if (_type == _WaitType.All) { bIsDone = true; foreach (var instruction in _arrInstructions) { if (!instruction.IsDone()) { bIsDone = false; break; } } } else if (_type == _WaitType.OneOf) { foreach (var instruction in _arrInstructions) { if (instruction.IsDone()) { _firstDoneInstruction = instruction; bIsDone = true; break; } } } else if (_type == _WaitType.NumOf) { if (_doneInstructions.Count != 0) { return(true); } else { Debugger.Assert(_doneInstructions.Count <= _arrInstructions.Length); int nNum = 0; foreach (var instruction in _arrInstructions) { if (instruction.IsDone()) { nNum++; if (nNum == _number) { bIsDone = true; break; } } } if (bIsDone) { foreach (var instruction in _arrInstructions) { if (instruction.IsDone()) { _doneInstructions.Add(instruction); } } } } } return(bIsDone); }
private void Yield(IYieldInstruction instruction) { State = CoroutineState.Continue; instruction.Yield(this, YieldReturn); }
public static IEnumerator DoAfter(Action method, IYieldInstruction yieldInstruction) { yield return(yieldInstruction.Wait()); method(); }
/// 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); }
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(); } }