Event.php 6.9 KB

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