Coroutine.php 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. <?php
  2. declare(strict_types=1);
  3. /**
  4. * This file is part of Hyperf.
  5. *
  6. * @link https://www.hyperf.io
  7. * @document https://hyperf.wiki
  8. * @contact group@hyperf.io
  9. * @license https://github.com/hyperf/hyperf/blob/master/LICENSE
  10. */
  11. namespace Hyperf\Utils;
  12. use Hyperf\Contract\StdoutLoggerInterface;
  13. use Hyperf\Engine\Coroutine as Co;
  14. use Hyperf\Engine\Exception\CoroutineDestroyedException;
  15. use Hyperf\Engine\Exception\RunningInNonCoroutineException;
  16. use Hyperf\ExceptionHandler\Formatter\FormatterInterface;
  17. use Psr\Log\LoggerInterface;
  18. use Throwable;
  19. class Coroutine
  20. {
  21. /**
  22. * Returns the current coroutine ID.
  23. * Returns -1 when running in non-coroutine context.
  24. */
  25. public static function id(): int
  26. {
  27. return Co::id();
  28. }
  29. public static function defer(callable $callable)
  30. {
  31. Co::defer($callable);
  32. }
  33. public static function sleep(float $seconds)
  34. {
  35. usleep(intval($seconds * 1000 * 1000));
  36. }
  37. /**
  38. * Returns the parent coroutine ID.
  39. * Returns 0 when running in the top level coroutine.
  40. * @throws RunningInNonCoroutineException when running in non-coroutine context
  41. * @throws CoroutineDestroyedException when the coroutine has been destroyed
  42. */
  43. public static function parentId(?int $coroutineId = null): int
  44. {
  45. return Co::pid($coroutineId);
  46. }
  47. /**
  48. * @return int Returns the coroutine ID of the coroutine just created.
  49. * Returns -1 when coroutine create failed.
  50. */
  51. public static function create(callable $callable): int
  52. {
  53. $coroutine = Co::create(function () use ($callable) {
  54. try {
  55. call($callable);
  56. } catch (Throwable $throwable) {
  57. if (ApplicationContext::hasContainer()) {
  58. $container = ApplicationContext::getContainer();
  59. if ($container->has(StdoutLoggerInterface::class)) {
  60. /* @var LoggerInterface $logger */
  61. $logger = $container->get(StdoutLoggerInterface::class);
  62. /* @var FormatterInterface $formatter */
  63. if ($container->has(FormatterInterface::class)) {
  64. $formatter = $container->get(FormatterInterface::class);
  65. $logger->warning($formatter->format($throwable));
  66. } else {
  67. $logger->warning(sprintf('Uncaptured exception[%s] detected in %s::%d.', get_class($throwable), $throwable->getFile(), $throwable->getLine()));
  68. }
  69. }
  70. }
  71. }
  72. });
  73. try {
  74. return $coroutine->getId();
  75. } catch (\Throwable $exception) {
  76. return -1;
  77. }
  78. }
  79. public static function inCoroutine(): bool
  80. {
  81. return Co::id() > 0;
  82. }
  83. }