Swoole.php 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  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 Ares<aresrr#qq.com>
  10. * @link http://www.workerman.net/
  11. * @link https://github.com/ares333/Workerman
  12. * @license http://www.opensource.org/licenses/mit-license.php MIT License
  13. */
  14. namespace Workerman\Events;
  15. use Workerman\Worker;
  16. use Swoole\Event;
  17. use Swoole\Timer;
  18. class Swoole implements EventInterface
  19. {
  20. protected $_timer = array();
  21. protected $_timerOnceMap = array();
  22. protected $mapId = 0;
  23. protected $_fd = array();
  24. // milisecond
  25. public static $signalDispatchInterval = 500;
  26. protected $_hasSignal = false;
  27. /**
  28. *
  29. * {@inheritdoc}
  30. *
  31. * @see \Workerman\Events\EventInterface::add()
  32. */
  33. public function add($fd, $flag, $func, $args = array())
  34. {
  35. switch ($flag) {
  36. case self::EV_SIGNAL:
  37. $res = \pcntl_signal($fd, $func, false);
  38. if (! $this->_hasSignal && $res) {
  39. Timer::tick(static::$signalDispatchInterval,
  40. function () {
  41. \pcntl_signal_dispatch();
  42. });
  43. $this->_hasSignal = true;
  44. }
  45. return $res;
  46. case self::EV_TIMER:
  47. case self::EV_TIMER_ONCE:
  48. $method = self::EV_TIMER === $flag ? 'tick' : 'after';
  49. if ($this->mapId > \PHP_INT_MAX) {
  50. $this->mapId = 0;
  51. }
  52. $mapId = $this->mapId++;
  53. $t = (int)($fd * 1000);
  54. if ($t < 1) {
  55. $t = 1;
  56. }
  57. $timer_id = Timer::$method($t,
  58. function ($timer_id = null) use ($func, $args, $mapId) {
  59. try {
  60. \call_user_func_array($func, (array)$args);
  61. } catch (\Exception $e) {
  62. Worker::stopAll(250, $e);
  63. } catch (\Error $e) {
  64. Worker::stopAll(250, $e);
  65. }
  66. // EV_TIMER_ONCE
  67. if (! isset($timer_id)) {
  68. // may be deleted in $func
  69. if (\array_key_exists($mapId, $this->_timerOnceMap)) {
  70. $timer_id = $this->_timerOnceMap[$mapId];
  71. unset($this->_timer[$timer_id],
  72. $this->_timerOnceMap[$mapId]);
  73. }
  74. }
  75. });
  76. if ($flag === self::EV_TIMER_ONCE) {
  77. $this->_timerOnceMap[$mapId] = $timer_id;
  78. $this->_timer[$timer_id] = $mapId;
  79. } else {
  80. $this->_timer[$timer_id] = null;
  81. }
  82. return $timer_id;
  83. case self::EV_READ:
  84. case self::EV_WRITE:
  85. $fd_key = (int) $fd;
  86. if (! isset($this->_fd[$fd_key])) {
  87. if ($flag === self::EV_READ) {
  88. $res = Event::add($fd, $func, null, SWOOLE_EVENT_READ);
  89. $fd_type = SWOOLE_EVENT_READ;
  90. } else {
  91. $res = Event::add($fd, null, $func, SWOOLE_EVENT_WRITE);
  92. $fd_type = SWOOLE_EVENT_WRITE;
  93. }
  94. if ($res) {
  95. $this->_fd[$fd_key] = $fd_type;
  96. }
  97. } else {
  98. $fd_val = $this->_fd[$fd_key];
  99. $res = true;
  100. if ($flag === self::EV_READ) {
  101. if (($fd_val & SWOOLE_EVENT_READ) !== SWOOLE_EVENT_READ) {
  102. $res = Event::set($fd, $func, null,
  103. SWOOLE_EVENT_READ | SWOOLE_EVENT_WRITE);
  104. $this->_fd[$fd_key] |= SWOOLE_EVENT_READ;
  105. }
  106. } else {
  107. if (($fd_val & SWOOLE_EVENT_WRITE) !== SWOOLE_EVENT_WRITE) {
  108. $res = Event::set($fd, null, $func,
  109. SWOOLE_EVENT_READ | SWOOLE_EVENT_WRITE);
  110. $this->_fd[$fd_key] |= SWOOLE_EVENT_WRITE;
  111. }
  112. }
  113. }
  114. return $res;
  115. }
  116. }
  117. /**
  118. *
  119. * {@inheritdoc}
  120. *
  121. * @see \Workerman\Events\EventInterface::del()
  122. */
  123. public function del($fd, $flag)
  124. {
  125. switch ($flag) {
  126. case self::EV_SIGNAL:
  127. return \pcntl_signal($fd, SIG_IGN, false);
  128. case self::EV_TIMER:
  129. case self::EV_TIMER_ONCE:
  130. // already remove in EV_TIMER_ONCE callback.
  131. if (! \array_key_exists($fd, $this->_timer)) {
  132. return true;
  133. }
  134. $res = Timer::clear($fd);
  135. if ($res) {
  136. $mapId = $this->_timer[$fd];
  137. if (isset($mapId)) {
  138. unset($this->_timerOnceMap[$mapId]);
  139. }
  140. unset($this->_timer[$fd]);
  141. }
  142. return $res;
  143. case self::EV_READ:
  144. case self::EV_WRITE:
  145. $fd_key = (int) $fd;
  146. if (isset($this->_fd[$fd_key])) {
  147. $fd_val = $this->_fd[$fd_key];
  148. if ($flag === self::EV_READ) {
  149. $flag_remove = ~ SWOOLE_EVENT_READ;
  150. } else {
  151. $flag_remove = ~ SWOOLE_EVENT_WRITE;
  152. }
  153. $fd_val &= $flag_remove;
  154. if (0 === $fd_val) {
  155. $res = Event::del($fd);
  156. if ($res) {
  157. unset($this->_fd[$fd_key]);
  158. }
  159. } else {
  160. $res = Event::set($fd, null, null, $fd_val);
  161. if ($res) {
  162. $this->_fd[$fd_key] = $fd_val;
  163. }
  164. }
  165. } else {
  166. $res = true;
  167. }
  168. return $res;
  169. }
  170. }
  171. /**
  172. *
  173. * {@inheritdoc}
  174. *
  175. * @see \Workerman\Events\EventInterface::clearAllTimer()
  176. */
  177. public function clearAllTimer()
  178. {
  179. foreach (array_keys($this->_timer) as $v) {
  180. Timer::clear($v);
  181. }
  182. $this->_timer = array();
  183. $this->_timerOnceMap = array();
  184. }
  185. /**
  186. *
  187. * {@inheritdoc}
  188. *
  189. * @see \Workerman\Events\EventInterface::loop()
  190. */
  191. public function loop()
  192. {
  193. Event::wait();
  194. }
  195. /**
  196. *
  197. * {@inheritdoc}
  198. *
  199. * @see \Workerman\Events\EventInterface::destroy()
  200. */
  201. public function destroy()
  202. {
  203. Event::exit();
  204. posix_kill(posix_getpid(), SIGINT);
  205. }
  206. /**
  207. *
  208. * {@inheritdoc}
  209. *
  210. * @see \Workerman\Events\EventInterface::getTimerCount()
  211. */
  212. public function getTimerCount()
  213. {
  214. return \count($this->_timer);
  215. }
  216. }