Swoole.php 6.8 KB

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