Timer.php 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. <?php
  2. /**
  3. * This file is part of workerman.
  4. *
  5. * Licensed under The MIT License
  6. * For full copyright and license information, please see the MIT-LICENSE.txt
  7. * Redistributions of files must retain the above copyright notice.
  8. *
  9. * @author walkor<walkor@workerman.net>
  10. * @copyright walkor<walkor@workerman.net>
  11. * @link http://www.workerman.net/
  12. * @license http://www.opensource.org/licenses/mit-license.php MIT License
  13. */
  14. namespace Workerman\Lib;
  15. use Workerman\Events\EventInterface;
  16. use Exception;
  17. /**
  18. * Timer.
  19. *
  20. * example:
  21. * Workerman\Lib\Timer::add($time_interval, callback, array($arg1, $arg2..));
  22. */
  23. class Timer
  24. {
  25. /**
  26. * Tasks that based on ALARM signal.
  27. * [
  28. * run_time => [[$func, $args, $persistent, time_interval],[$func, $args, $persistent, time_interval],..]],
  29. * run_time => [[$func, $args, $persistent, time_interval],[$func, $args, $persistent, time_interval],..]],
  30. * ..
  31. * ]
  32. *
  33. * @var array
  34. */
  35. protected static $_tasks = array();
  36. /**
  37. * event
  38. *
  39. * @var \Workerman\Events\EventInterface
  40. */
  41. protected static $_event = null;
  42. /**
  43. * Init.
  44. *
  45. * @param \Workerman\Events\EventInterface $event
  46. * @return void
  47. */
  48. public static function init($event = null)
  49. {
  50. if ($event) {
  51. self::$_event = $event;
  52. } else {
  53. pcntl_signal(SIGALRM, array('\Workerman\Lib\Timer', 'signalHandle'), false);
  54. }
  55. }
  56. /**
  57. * ALARM signal handler.
  58. *
  59. * @return void
  60. */
  61. public static function signalHandle()
  62. {
  63. if (!self::$_event) {
  64. pcntl_alarm(1);
  65. self::tick();
  66. }
  67. }
  68. /**
  69. * Add a timer.
  70. *
  71. * @param int $time_interval
  72. * @param callback $func
  73. * @param mixed $args
  74. * @param bool $persistent
  75. * @return bool
  76. */
  77. public static function add($time_interval, $func, $args = array(), $persistent = true)
  78. {
  79. if ($time_interval <= 0) {
  80. echo new Exception("bad time_interval");
  81. return false;
  82. }
  83. if (self::$_event) {
  84. return self::$_event->add($time_interval,
  85. $persistent ? EventInterface::EV_TIMER : EventInterface::EV_TIMER_ONCE, $func, $args);
  86. }
  87. if (!is_callable($func)) {
  88. echo new Exception("not callable");
  89. return false;
  90. }
  91. if (empty(self::$_tasks)) {
  92. pcntl_alarm(1);
  93. }
  94. $time_now = time();
  95. $run_time = $time_now + $time_interval;
  96. if (!isset(self::$_tasks[$run_time])) {
  97. self::$_tasks[$run_time] = array();
  98. }
  99. self::$_tasks[$run_time][] = array($func, (array)$args, $persistent, $time_interval);
  100. return true;
  101. }
  102. /**
  103. * Tick.
  104. *
  105. * @return void
  106. */
  107. public static function tick()
  108. {
  109. if (empty(self::$_tasks)) {
  110. pcntl_alarm(0);
  111. return;
  112. }
  113. $time_now = time();
  114. foreach (self::$_tasks as $run_time => $task_data) {
  115. if ($time_now >= $run_time) {
  116. foreach ($task_data as $index => $one_task) {
  117. $task_func = $one_task[0];
  118. $task_args = $one_task[1];
  119. $persistent = $one_task[2];
  120. $time_interval = $one_task[3];
  121. try {
  122. call_user_func_array($task_func, $task_args);
  123. } catch (\Exception $e) {
  124. echo $e;
  125. }
  126. if ($persistent) {
  127. self::add($time_interval, $task_func, $task_args);
  128. }
  129. }
  130. unset(self::$_tasks[$run_time]);
  131. }
  132. }
  133. }
  134. /**
  135. * Remove a timer.
  136. *
  137. * @param mixed $timer_id
  138. * @return bool
  139. */
  140. public static function del($timer_id)
  141. {
  142. if (self::$_event) {
  143. return self::$_event->del($timer_id, EventInterface::EV_TIMER);
  144. }
  145. return false;
  146. }
  147. /**
  148. * Remove all timers.
  149. *
  150. * @return void
  151. */
  152. public static function delAll()
  153. {
  154. self::$_tasks = array();
  155. pcntl_alarm(0);
  156. if (self::$_event) {
  157. self::$_event->clearAllTimer();
  158. }
  159. }
  160. }