Swoole.php 7.0 KB

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