friendship ended with social-app. php is my new best friend
1<?php 2 3namespace React\EventLoop; 4 5use BadMethodCallException; 6use libev\EventLoop; 7use libev\IOEvent; 8use libev\SignalEvent; 9use libev\TimerEvent; 10use React\EventLoop\Tick\FutureTickQueue; 11use React\EventLoop\Timer\Timer; 12use SplObjectStorage; 13 14/** 15 * [Deprecated] An `ext-libev` based event loop. 16 * 17 * This uses an [unofficial `libev` extension](https://github.com/m4rw3r/php-libev), 18 * that provides an interface to `libev` library. 19 * `libev` itself supports a number of system-specific backends (epoll, kqueue). 20 * 21 * This loop does only work with PHP 5. 22 * An update for PHP 7 is [unlikely](https://github.com/m4rw3r/php-libev/issues/8) 23 * to happen any time soon. 24 * 25 * @see https://github.com/m4rw3r/php-libev 26 * @see https://gist.github.com/1688204 27 * @deprecated 1.2.0, use [`ExtEvLoop`](#extevloop) instead. 28 */ 29final class ExtLibevLoop implements LoopInterface 30{ 31 private $loop; 32 private $futureTickQueue; 33 private $timerEvents; 34 private $readEvents = array(); 35 private $writeEvents = array(); 36 private $running; 37 private $signals; 38 private $signalEvents = array(); 39 40 public function __construct() 41 { 42 if (!\class_exists('libev\EventLoop', false)) { 43 throw new BadMethodCallException('Cannot create ExtLibevLoop, ext-libev extension missing'); 44 } 45 46 $this->loop = new EventLoop(); 47 $this->futureTickQueue = new FutureTickQueue(); 48 $this->timerEvents = new SplObjectStorage(); 49 $this->signals = new SignalsHandler(); 50 } 51 52 public function addReadStream($stream, $listener) 53 { 54 if (isset($this->readEvents[(int) $stream])) { 55 return; 56 } 57 58 $callback = function () use ($stream, $listener) { 59 \call_user_func($listener, $stream); 60 }; 61 62 $event = new IOEvent($callback, $stream, IOEvent::READ); 63 $this->loop->add($event); 64 65 $this->readEvents[(int) $stream] = $event; 66 } 67 68 public function addWriteStream($stream, $listener) 69 { 70 if (isset($this->writeEvents[(int) $stream])) { 71 return; 72 } 73 74 $callback = function () use ($stream, $listener) { 75 \call_user_func($listener, $stream); 76 }; 77 78 $event = new IOEvent($callback, $stream, IOEvent::WRITE); 79 $this->loop->add($event); 80 81 $this->writeEvents[(int) $stream] = $event; 82 } 83 84 public function removeReadStream($stream) 85 { 86 $key = (int) $stream; 87 88 if (isset($this->readEvents[$key])) { 89 $this->readEvents[$key]->stop(); 90 $this->loop->remove($this->readEvents[$key]); 91 unset($this->readEvents[$key]); 92 } 93 } 94 95 public function removeWriteStream($stream) 96 { 97 $key = (int) $stream; 98 99 if (isset($this->writeEvents[$key])) { 100 $this->writeEvents[$key]->stop(); 101 $this->loop->remove($this->writeEvents[$key]); 102 unset($this->writeEvents[$key]); 103 } 104 } 105 106 public function addTimer($interval, $callback) 107 { 108 $timer = new Timer( $interval, $callback, false); 109 110 $that = $this; 111 $timers = $this->timerEvents; 112 $callback = function () use ($timer, $timers, $that) { 113 \call_user_func($timer->getCallback(), $timer); 114 115 if ($timers->contains($timer)) { 116 $that->cancelTimer($timer); 117 } 118 }; 119 120 $event = new TimerEvent($callback, $timer->getInterval()); 121 $this->timerEvents->attach($timer, $event); 122 $this->loop->add($event); 123 124 return $timer; 125 } 126 127 public function addPeriodicTimer($interval, $callback) 128 { 129 $timer = new Timer($interval, $callback, true); 130 131 $callback = function () use ($timer) { 132 \call_user_func($timer->getCallback(), $timer); 133 }; 134 135 $event = new TimerEvent($callback, $timer->getInterval(), $timer->getInterval()); 136 $this->timerEvents->attach($timer, $event); 137 $this->loop->add($event); 138 139 return $timer; 140 } 141 142 public function cancelTimer(TimerInterface $timer) 143 { 144 if (isset($this->timerEvents[$timer])) { 145 $this->loop->remove($this->timerEvents[$timer]); 146 $this->timerEvents->detach($timer); 147 } 148 } 149 150 public function futureTick($listener) 151 { 152 $this->futureTickQueue->add($listener); 153 } 154 155 public function addSignal($signal, $listener) 156 { 157 $this->signals->add($signal, $listener); 158 159 if (!isset($this->signalEvents[$signal])) { 160 $signals = $this->signals; 161 $this->signalEvents[$signal] = new SignalEvent(function () use ($signals, $signal) { 162 $signals->call($signal); 163 }, $signal); 164 $this->loop->add($this->signalEvents[$signal]); 165 } 166 } 167 168 public function removeSignal($signal, $listener) 169 { 170 $this->signals->remove($signal, $listener); 171 172 if (isset($this->signalEvents[$signal]) && $this->signals->count($signal) === 0) { 173 $this->signalEvents[$signal]->stop(); 174 $this->loop->remove($this->signalEvents[$signal]); 175 unset($this->signalEvents[$signal]); 176 } 177 } 178 179 public function run() 180 { 181 $this->running = true; 182 183 while ($this->running) { 184 $this->futureTickQueue->tick(); 185 186 $flags = EventLoop::RUN_ONCE; 187 if (!$this->running || !$this->futureTickQueue->isEmpty()) { 188 $flags |= EventLoop::RUN_NOWAIT; 189 } elseif (!$this->readEvents && !$this->writeEvents && !$this->timerEvents->count() && $this->signals->isEmpty()) { 190 break; 191 } 192 193 $this->loop->run($flags); 194 } 195 } 196 197 public function stop() 198 { 199 $this->running = false; 200 } 201}