WaitGroup.php 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  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\Coroutine;
  12. use BadMethodCallException;
  13. use Hyperf\Engine\Channel;
  14. use InvalidArgumentException;
  15. /**
  16. * This file mostly code come from `swoole/library`.
  17. */
  18. class WaitGroup
  19. {
  20. protected Channel $chan;
  21. protected int $count = 0;
  22. protected bool $waiting = false;
  23. public function __construct(int $delta = 0)
  24. {
  25. $this->chan = new Channel(1);
  26. if ($delta > 0) {
  27. $this->add($delta);
  28. }
  29. }
  30. public function add(int $delta = 1): void
  31. {
  32. if ($this->waiting) {
  33. throw new BadMethodCallException('WaitGroup misuse: add called concurrently with wait');
  34. }
  35. $count = $this->count + $delta;
  36. if ($count < 0) {
  37. throw new InvalidArgumentException('WaitGroup misuse: negative counter');
  38. }
  39. $this->count = $count;
  40. }
  41. public function done(): void
  42. {
  43. $count = $this->count - 1;
  44. if ($count < 0) {
  45. throw new BadMethodCallException('WaitGroup misuse: negative counter');
  46. }
  47. $this->count = $count;
  48. if ($count === 0 && $this->waiting) {
  49. $this->chan->push(true);
  50. }
  51. }
  52. public function wait(float $timeout = -1): bool
  53. {
  54. if ($this->waiting) {
  55. throw new BadMethodCallException('WaitGroup misuse: reused before previous wait has returned');
  56. }
  57. if ($this->count > 0) {
  58. $this->waiting = true;
  59. $done = $this->chan->pop($timeout);
  60. $this->waiting = false;
  61. return $done;
  62. }
  63. return true;
  64. }
  65. public function count(): int
  66. {
  67. return $this->count;
  68. }
  69. }