Swoole.php 6.9 KB

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