routine = $routine; $this->context = $context; $this->controller = $controller; $this->stack = new \SplStack(); $this->id = $context->getLogId(); $this->callBack = $callBack; } /** * 重置迭代器 * * @param \Generator $routine 迭代器实例 * @return $this */ public function resetRoutine(\Generator $routine = null) { $this->routine = null; $this->routine = $routine; return $this; } /** * 获取callback * * @return mixed */ public function getCallBack() { return $this->callBack; } /** * 重置callback * * @param callable|null $callBack 迭代器执行完成后回调函数 * @return $this */ public function resetCallBack(callable $callBack = null) { $this->callBack = null; $this->callBack = $callBack; return $this; } /** * 获取controller * * @return Controller */ public function getController() { return $this->controller; } /** * 设置调度时产生的异常 * * @param \Throwable $exception 异常实例 */ public function setException(\Throwable $exception) { $this->exception = $exception; } /** * 请求的协程调度 */ public function run() { try { if ($this->exception) { throw $this->exception; } $value = $this->routine->current(); //嵌套的协程 if ($value instanceof \Generator) { $this->stack->push($this->routine); $this->routine = $value; $value = null; return; } if ($value != null && $value instanceof IBase) { if ($value->isTimeout()) { try { $value->throwTimeOutException(); } catch (\Exception $e) { $this->handleTaskTimeout($e, $value); } unset($value); $this->routine->send(false); } else { $result = $value->getResult(); if ($result !== CNull::getInstance()) { $this->routine->send($result); } while (!$this->routine->valid() && !empty($this->stack) && !$this->stack->isEmpty()) { try { $result = $this->routine->getReturn(); } catch (\Throwable $e) { // not todo $result = false; } $this->routine = null; $this->routine = $this->stack->pop(); $this->routine->send($result); } } } else { if ($this->routine instanceof \Generator && $this->routine->valid()) { $this->routine->send($value); } else { try { $result = $this->routine->getReturn(); } catch (\Throwable $e) { // not todo $result = false; } if (!empty($this->stack) && !$this->stack->isEmpty()) { $this->routine = null; $this->routine = $this->stack->pop(); } $this->routine->send($result); } } } catch (\Throwable $e) { $this->exception = null; if (empty($value)) { $value = ''; } $runTaskException = $this->handleTaskException($e, $value); if ($runTaskException instanceof \Throwable) { if ($this->controller) { $this->controller->onExceptionHandle($runTaskException); } else { $this->routine->throw($runTaskException); } } unset($value); } } /** * 处理协程任务的超时 * * @param \Throwable $e 异常实例 * @param mixed $value 当前迭代的值 * @return \Throwable */ public function handleTaskTimeout(\Throwable $e, $value) { if ($value != '') { $logValue = ''; dumpInternal($logValue, $value, 0, false); $message = '' . $logValue . ' message: ' . $e->getMessage(); } else { $message = 'message: ' . $e->getMessage(); } $this->getContext()->getLog()->warning($message); if (!empty($value) && $value instanceof IBase && method_exists($value, 'destroy')) { $value->destroy(); } return $e; } /** * 处理协程任务的异常 * * @param \Throwable $e 异常实例 * @param mixed $value 当前迭代的值 * @return bool|Exception|\Throwable */ public function handleTaskException(\Throwable $e, $value) { while (!empty($this->stack) && !$this->stack->isEmpty()) { $this->routine = $this->stack->pop(); try { $this->routine->throw($e); break; } catch (\Exception $e) { } } if (!empty($value) && $value instanceof IBase && method_exists($value, 'destroy')) { $value->destroy(); } if (!empty($this->stack) && $this->stack->isEmpty()) { return $e; } return true; } /** * [isFinished 判断该task是否完成] * @return boolean [description] */ public function isFinished() { return (empty($this->stack) || $this->stack->isEmpty()) && !$this->routine->valid(); } /** * 获取协程任务当前正在运行的迭代器 * * @return \Generator */ public function getRoutine() { return $this->routine; } /** * 销毁 */ public function destroy() { if (!empty($this->id)) { getInstance()->scheduler->taskMap[$this->id] = null; unset(getInstance()->scheduler->taskMap[$this->id]); getInstance()->scheduler->IOCallBack[$this->id] = null; unset(getInstance()->scheduler->IOCallBack[$this->id]); $this->stack = null; $this->controller = null; $this->id = null; $this->callBack = null; } } }