Timer.php 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. <?php
  2. namespace Workerman\Lib;
  3. use \Workerman\Events\EventInterface;
  4. use \Exception;
  5. /**
  6. *
  7. * timer
  8. *
  9. * <b>example:</b>
  10. * <pre>
  11. * <code>
  12. * Workerman\Lib\Timer::init();
  13. * Workerman\Lib\Timer::add($time_interval, callback, array($arg1, $arg2..));
  14. * <code>
  15. * </pre>
  16. * @author walkor <walkor@workerman.net>
  17. */
  18. class Timer
  19. {
  20. /**
  21. * [
  22. * run_time => [[$func, $args, $persistent, timelong],[$func, $args, $persistent, timelong],..]],
  23. * run_time => [[$func, $args, $persistent, timelong],[$func, $args, $persistent, timelong],..]],
  24. * ..
  25. * ]
  26. * @var array
  27. */
  28. protected static $tasks = array();
  29. /**
  30. * init
  31. * @return void
  32. */
  33. public static function init($event = null)
  34. {
  35. if($event)
  36. {
  37. $event->add(SIGALRM, EventInterface::EV_SIGNAL, array('\Workerman\Lib\Timer', 'signalHandle'));
  38. }
  39. else
  40. {
  41. pcntl_signal(SIGALRM, array('\Workerman\Lib\Timer', 'signalHandle'), false);
  42. }
  43. }
  44. /**
  45. * signal handler
  46. * @return void
  47. */
  48. public static function signalHandle()
  49. {
  50. pcntl_alarm(1);
  51. self::tick();
  52. }
  53. /**
  54. * add a timer
  55. * @param int $time_interval
  56. * @param callback $func
  57. * @param mix $args
  58. * @return void
  59. */
  60. public static function add($time_interval, $func, $args = array(), $persistent = true)
  61. {
  62. if($time_interval <= 0)
  63. {
  64. return false;
  65. }
  66. if(!is_callable($func))
  67. {
  68. echo new Exception("not callable");
  69. return false;
  70. }
  71. if(empty(self::$tasks))
  72. {
  73. pcntl_alarm(1);
  74. }
  75. $time_now = time();
  76. $run_time = $time_now + $time_interval;
  77. if(!isset(self::$tasks[$run_time]))
  78. {
  79. self::$tasks[$run_time] = array();
  80. }
  81. self::$tasks[$run_time][] = array($func, $args, $persistent, $time_interval);
  82. return true;
  83. }
  84. /**
  85. * tick
  86. * @return void
  87. */
  88. public static function tick()
  89. {
  90. if(empty(self::$tasks))
  91. {
  92. pcntl_alarm(0);
  93. return;
  94. }
  95. $time_now = time();
  96. foreach (self::$tasks as $run_time=>$task_data)
  97. {
  98. if($time_now >= $run_time)
  99. {
  100. foreach($task_data as $index=>$one_task)
  101. {
  102. $task_func = $one_task[0];
  103. $task_args = $one_task[1];
  104. $persistent = $one_task[2];
  105. $time_interval = $one_task[3];
  106. try
  107. {
  108. call_user_func_array($task_func, $task_args);
  109. }
  110. catch(\Exception $e)
  111. {
  112. echo $e;
  113. }
  114. if($persistent)
  115. {
  116. self::add($time_interval, $task_func, $task_args);
  117. }
  118. }
  119. unset(self::$tasks[$run_time]);
  120. }
  121. }
  122. }
  123. /**
  124. * del all
  125. */
  126. public static function delAll()
  127. {
  128. self::$tasks = array();
  129. pcntl_alarm(0);
  130. }
  131. }