timerman.php 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. <?php
  2. /**
  3. * 定时器管理类
  4. */
  5. class TimerMan
  6. {
  7. /**
  8. * 定时器列表
  9. * @var array
  10. */
  11. protected $timers;
  12. /**
  13. * ID值
  14. * @int
  15. */
  16. protected $id;
  17. /**
  18. * 定时器到期时间
  19. */
  20. protected $nextTimeout;
  21. /**
  22. * 构造函数
  23. */
  24. public function __construct()
  25. {
  26. $this->timers = [];
  27. $this->nextTimeout = 0;
  28. }
  29. /**
  30. * 添加定时器
  31. * @param int $ms 毫秒数
  32. * @param mixed $handle 回调函数
  33. * @param mixed $args 回调函数参数
  34. * @return int 定时器ID
  35. */
  36. public function add($ms, $handle, $args = [])
  37. {
  38. $now = floor(microtime(true) * 1000);
  39. $to = $now + $ms;
  40. if (!$this->nextTimeout || $to < $this->nextTimeout) {
  41. $this->nextTimeout = $to;
  42. }
  43. $this->timers[++$this->id] = [
  44. $to,
  45. $handle,
  46. is_array($args) ? $args : [$args],
  47. ];
  48. return $this->id;
  49. }
  50. /**
  51. * 清除定时器
  52. * @param int $id 定时器ID
  53. */
  54. public function clear($id)
  55. {
  56. if (isset($this->timers[$id])) {
  57. unset($this->timers[$id]);
  58. }
  59. }
  60. /**
  61. * 取select应当等待的时长
  62. */
  63. public function getWaitTime()
  64. {
  65. if (!$this->nextTimeout) {
  66. return [NULL, NULL];
  67. }
  68. $now = floor(microtime(true) * 1000);
  69. if ($now >= $this->nextTimeout) {
  70. return [NULL, NULL];
  71. }
  72. $ms = $this->nextTimeout - $now;
  73. if ($ms < 10) {
  74. return [0, 10];
  75. }
  76. return [floor($ms/1000), $ms%1000];
  77. }
  78. /**
  79. * 定时器的循环检测代码
  80. */
  81. public function interval()
  82. {
  83. $cnt = 0;
  84. $now = floor(microtime(true) * 1000) + 10; //误差10
  85. $timeouted = [];
  86. $min = 0;
  87. foreach ($this->timers as $id => $item) {
  88. if ($item[0] <= $now) {
  89. $timeouted[$id] = $item;
  90. unset($this->timers[$id]);
  91. }
  92. $min = $min == 0 ? $item[0] : min($min, $item[0]);
  93. }
  94. foreach ($timeouted as $id => $item) {
  95. call_user_func_array($item[1], $item[2]);
  96. }
  97. $this->nextTimeout = $min;
  98. }
  99. }