Event.php 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  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 walkor<walkor@workerman.net>
  10. * @copyright walkor<walkor@workerman.net>
  11. * @link http://www.workerman.net/
  12. * @license http://www.opensource.org/licenses/mit-license.php MIT License
  13. */
  14. namespace Workerman\Events;
  15. use Throwable;
  16. /**
  17. * libevent eventloop
  18. */
  19. class Event implements EventInterface
  20. {
  21. /**
  22. * Event base.
  23. * @var object
  24. */
  25. protected $eventBase = null;
  26. /**
  27. * All listeners for read event.
  28. * @var array
  29. */
  30. protected $readEvents = [];
  31. /**
  32. * All listeners for write event.
  33. * @var array
  34. */
  35. protected $writeEvents = [];
  36. /**
  37. * Event listeners of signal.
  38. * @var array
  39. */
  40. protected $eventSignal = [];
  41. /**
  42. * All timer event listeners.
  43. * [func, args, event, flag, time_interval]
  44. * @var array
  45. */
  46. protected $eventTimer = [];
  47. /**
  48. * Timer id.
  49. * @var int
  50. */
  51. protected $timerId = 0;
  52. /**
  53. * Event class name.
  54. * @var string
  55. */
  56. protected $eventClassName = '';
  57. /**
  58. * @var Closure || null
  59. */
  60. protected $errorHandler;
  61. /**
  62. * Construct.
  63. * @return void
  64. */
  65. public function __construct()
  66. {
  67. if (\class_exists('\\\\Event', false)) {
  68. $className = '\\\\Event';
  69. } else {
  70. $className = '\Event';
  71. }
  72. $this->eventClassName = $className;
  73. if (\class_exists('\\\\EventBase', false)) {
  74. $className = '\\\\EventBase';
  75. } else {
  76. $className = '\EventBase';
  77. }
  78. $this->eventBase = new $className();
  79. }
  80. /**
  81. * {@inheritdoc}
  82. */
  83. public function delay(float $delay, $func, $args = [])
  84. {
  85. $className = $this->eventClassName;
  86. $timerId = $this->timerId++;
  87. $event = new $className($this->eventBase, -1, $className::TIMEOUT, function () use ($func, $args) {
  88. try {
  89. $func(...$args);
  90. } catch (\Throwable $e) {
  91. $this->error($e);
  92. }
  93. });
  94. if (!$event || !$event->addTimer($delay)) {
  95. return false;
  96. }
  97. $this->eventTimer[$timerId] = $event;
  98. return $timerId;
  99. }
  100. /**
  101. * {@inheritdoc}
  102. */
  103. public function offDelay($timerId)
  104. {
  105. if (isset($this->eventTimer[$timerId])) {
  106. $this->eventTimer[$timerId]->del();
  107. unset($this->eventTimer[$timerId]);
  108. return true;
  109. }
  110. return false;
  111. }
  112. /**
  113. * {@inheritdoc}
  114. */
  115. public function offRepeat($timerId)
  116. {
  117. return $this->offDelay($timerId);
  118. }
  119. /**
  120. * {@inheritdoc}
  121. */
  122. public function repeat(float $interval, $func, $args = [])
  123. {
  124. $className = $this->eventClassName;
  125. $timerId = $this->timerId++;
  126. $event = new $className($this->eventBase, -1, $className::TIMEOUT | $className::PERSIST, function () use ($func, $args) {
  127. try {
  128. $func(...$args);
  129. } catch (\Throwable $e) {
  130. $this->error($e);
  131. }
  132. });
  133. if (!$event || !$event->addTimer($interval)) {
  134. return false;
  135. }
  136. $this->eventTimer[$timerId] = $event;
  137. return $timerId;
  138. }
  139. /**
  140. * {@inheritdoc}
  141. */
  142. public function onReadable($stream, $func)
  143. {
  144. $className = $this->eventClassName;
  145. $fdKey = (int)$stream;
  146. $event = new $this->eventClassName($this->eventBase, $stream, $className::READ | $className::PERSIST, $func, $stream);
  147. if (!$event || !$event->add()) {
  148. return false;
  149. }
  150. $this->readEvents[$fdKey] = $event;
  151. return true;
  152. }
  153. /**
  154. * {@inheritdoc}
  155. */
  156. public function offReadable($stream)
  157. {
  158. $fdKey = (int)$stream;
  159. if (isset($this->readEvents[$fdKey])) {
  160. $this->readEvents[$fdKey]->del();
  161. unset($this->readEvents[$fdKey]);
  162. }
  163. }
  164. /**
  165. * {@inheritdoc}
  166. */
  167. public function onWritable($stream, $func)
  168. {
  169. $className = $this->eventClassName;
  170. $fdKey = (int)$stream;
  171. $event = new $this->eventClassName($this->eventBase, $stream, $className::WRITE | $className::PERSIST, $func, $stream);
  172. if (!$event || !$event->add()) {
  173. return false;
  174. }
  175. $this->writeEvents[$fdKey] = $event;
  176. return true;
  177. }
  178. /**
  179. * {@inheritdoc}
  180. */
  181. public function offWritable($stream)
  182. {
  183. $fdKey = (int)$stream;
  184. if (isset($this->writeEvents[$fdKey])) {
  185. $this->writeEvents[$fdKey]->del();
  186. unset($this->writeEvents[$fdKey]);
  187. }
  188. }
  189. /**
  190. * {@inheritdoc}
  191. */
  192. public function onSignal($signal, $func)
  193. {
  194. $className = $this->eventClassName;
  195. $fdKey = (int)$signal;
  196. $event = $className::signal($this->eventBase, $signal, $func);
  197. if (!$event || !$event->add()) {
  198. return false;
  199. }
  200. $this->eventSignal[$fdKey] = $event;
  201. return true;
  202. }
  203. /**
  204. * {@inheritdoc}
  205. */
  206. public function offSignal($signal)
  207. {
  208. $fdKey = (int)$signal;
  209. if (isset($this->eventSignal[$fdKey])) {
  210. $this->eventSignal[$fdKey]->del();
  211. unset($this->eventSignal[$fdKey]);
  212. }
  213. }
  214. /**
  215. * {@inheritdoc}
  216. */
  217. public function deleteAllTimer()
  218. {
  219. foreach ($this->eventTimer as $event) {
  220. $event->del();
  221. }
  222. $this->eventTimer = [];
  223. }
  224. /**
  225. * {@inheritdoc}
  226. */
  227. public function run()
  228. {
  229. $this->eventBase->loop();
  230. }
  231. /**
  232. * {@inheritdoc}
  233. */
  234. public function stop()
  235. {
  236. $this->eventBase->exit();
  237. }
  238. /**
  239. * {@inheritdoc}
  240. */
  241. public function getTimerCount()
  242. {
  243. return \count($this->eventTimer);
  244. }
  245. /**
  246. * {@inheritdoc}
  247. */
  248. public function setErrorHandler($errorHandler)
  249. {
  250. $this->errorHandler = $errorHandler;
  251. }
  252. /**
  253. * {@inheritdoc}
  254. */
  255. public function getErrorHandler()
  256. {
  257. return $this->errorHandler;
  258. }
  259. /**
  260. * @param Throwable $e
  261. * @return void
  262. * @throws Throwable
  263. */
  264. public function error(Throwable $e)
  265. {
  266. try {
  267. if (!$this->errorHandler) {
  268. throw new $e;
  269. }
  270. ($this->errorHandler)($e);
  271. } catch (\Throwable $e) {
  272. // Cannot trigger an exception in the Event callback, otherwise it will cause an infinite loop
  273. echo $e;
  274. }
  275. }
  276. }