Select.php 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. <?php
  2. namespace Workerman\Events;
  3. class Select implements EventInterface
  4. {
  5. /**
  6. * all events
  7. * @var array
  8. */
  9. public $_allEvents = array();
  10. /**
  11. * all signal events
  12. * @var array
  13. */
  14. public $_signalEvents = array();
  15. /**
  16. * read fds
  17. * @var array
  18. */
  19. protected $_readFds = array();
  20. /**
  21. * write fds
  22. * @var array
  23. */
  24. protected $_writeFds = array();
  25. /**
  26. * add
  27. * @see Events\EventInterface::add()
  28. */
  29. public function add($fd, $flag, $func)
  30. {
  31. // key
  32. $fd_key = (int)$fd;
  33. switch ($flag)
  34. {
  35. case self::EV_READ:
  36. $this->_allEvents[$fd_key][$flag] = array($func, $fd);
  37. $this->_readFds[$fd_key] = $fd;
  38. break;
  39. case self::EV_WRITE:
  40. $this->_allEvents[$fd_key][$flag] = array($func, $fd);
  41. $this->_writeFds[$fd_key] = $fd;
  42. break;
  43. case self::EV_SIGNAL:
  44. $this->_signalEvents[$fd_key][$flag] = array($func, $fd);
  45. pcntl_signal($fd, array($this, 'signalHandler'));
  46. break;
  47. }
  48. return true;
  49. }
  50. /**
  51. * signal handler
  52. * @param int $signal
  53. */
  54. public function signalHandler($signal)
  55. {
  56. call_user_func_array($this->_signalEvents[$signal][self::EV_SIGNAL][0], array($signal));
  57. }
  58. /**
  59. * del
  60. * @see Events\EventInterface::del()
  61. */
  62. public function del($fd ,$flag)
  63. {
  64. $fd_key = (int)$fd;
  65. switch ($flag)
  66. {
  67. case self::EV_READ:
  68. unset($this->_allEvents[$fd_key][$flag], $this->_readFds[$fd_key]);
  69. if(empty($this->_allEvents[$fd_key]))
  70. {
  71. unset($this->_allEvents[$fd_key]);
  72. }
  73. break;
  74. case self::EV_WRITE:
  75. unset($this->_allEvents[$fd_key][$flag], $this->_writeFds[$fd_key]);
  76. if(empty($this->_allEvents[$fd_key]))
  77. {
  78. unset($this->_allEvents[$fd_key]);
  79. }
  80. break;
  81. case self::EV_SIGNAL:
  82. unset($this->_signalEvents[$fd_key]);
  83. pcntl_signal($fd, SIG_IGN);
  84. break;
  85. }
  86. return true;
  87. }
  88. /**
  89. * main loop
  90. * @see Events\EventInterface::loop()
  91. */
  92. public function loop()
  93. {
  94. $e = null;
  95. while (1)
  96. {
  97. // calls signal handlers for pending signals
  98. pcntl_signal_dispatch();
  99. //
  100. $read = $this->_readFds;
  101. $write = $this->_writeFds;
  102. // waits for $read and $write to change status
  103. if(!@stream_select($read, $write, $e, PHP_INT_MAX))
  104. {
  105. // maybe interrupt by sianals, so calls signal handlers for pending signals
  106. pcntl_signal_dispatch();
  107. continue;
  108. }
  109. // read
  110. if($read)
  111. {
  112. foreach($read as $fd)
  113. {
  114. $fd_key = (int) $fd;
  115. if(isset($this->_allEvents[$fd_key][self::EV_READ]))
  116. {
  117. call_user_func_array($this->_allEvents[$fd_key][self::EV_READ][0], array($this->_allEvents[$fd_key][self::EV_READ][1]));
  118. }
  119. }
  120. }
  121. // write
  122. if($write)
  123. {
  124. foreach($write as $fd)
  125. {
  126. $fd_key = (int) $fd;
  127. if(isset($this->_allEvents[$fd_key][self::EV_WRITE]))
  128. {
  129. call_user_func_array($this->_allEvents[$fd_key][self::EV_WRITE][0], array($this->_allEvents[$fd_key][self::EV_WRITE][1]));
  130. }
  131. }
  132. }
  133. }
  134. }
  135. }