mirror of
https://github.com/Yetangitu/ampache
synced 2025-10-05 10:49:37 +02:00
Move from React 0.4.0 to 0.3.4 for PHP 5.3 compatibility reasons
This commit is contained in:
parent
d3f01a3bc7
commit
7f82bea13e
50 changed files with 608 additions and 1937 deletions
|
@ -2,258 +2,188 @@
|
|||
|
||||
namespace React\EventLoop;
|
||||
|
||||
use React\EventLoop\Tick\FutureTickQueue;
|
||||
use React\EventLoop\Tick\NextTickQueue;
|
||||
use React\EventLoop\Timer\Timer;
|
||||
use React\EventLoop\Timer\TimerInterface;
|
||||
use React\EventLoop\Timer\Timers;
|
||||
|
||||
/**
|
||||
* A stream_select() based event-loop.
|
||||
*/
|
||||
class StreamSelectLoop implements LoopInterface
|
||||
{
|
||||
const MICROSECONDS_PER_SECOND = 1000000;
|
||||
const QUANTUM_INTERVAL = 1000000;
|
||||
|
||||
private $nextTickQueue;
|
||||
private $futureTickQueue;
|
||||
private $timers;
|
||||
private $readStreams = [];
|
||||
private $readListeners = [];
|
||||
private $writeStreams = [];
|
||||
private $writeListeners = [];
|
||||
private $running;
|
||||
private $running = false;
|
||||
private $readStreams = array();
|
||||
private $readListeners = array();
|
||||
private $writeStreams = array();
|
||||
private $writeListeners = array();
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->nextTickQueue = new NextTickQueue($this);
|
||||
$this->futureTickQueue = new FutureTickQueue($this);
|
||||
$this->timers = new Timers();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function addReadStream($stream, callable $listener)
|
||||
public function addReadStream($stream, $listener)
|
||||
{
|
||||
$key = (int) $stream;
|
||||
$id = (int) $stream;
|
||||
|
||||
if (!isset($this->readStreams[$key])) {
|
||||
$this->readStreams[$key] = $stream;
|
||||
$this->readListeners[$key] = $listener;
|
||||
if (!isset($this->readStreams[$id])) {
|
||||
$this->readStreams[$id] = $stream;
|
||||
$this->readListeners[$id] = $listener;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function addWriteStream($stream, callable $listener)
|
||||
public function addWriteStream($stream, $listener)
|
||||
{
|
||||
$key = (int) $stream;
|
||||
$id = (int) $stream;
|
||||
|
||||
if (!isset($this->writeStreams[$key])) {
|
||||
$this->writeStreams[$key] = $stream;
|
||||
$this->writeListeners[$key] = $listener;
|
||||
if (!isset($this->writeStreams[$id])) {
|
||||
$this->writeStreams[$id] = $stream;
|
||||
$this->writeListeners[$id] = $listener;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function removeReadStream($stream)
|
||||
{
|
||||
$key = (int) $stream;
|
||||
$id = (int) $stream;
|
||||
|
||||
unset(
|
||||
$this->readStreams[$key],
|
||||
$this->readListeners[$key]
|
||||
$this->readStreams[$id],
|
||||
$this->readListeners[$id]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function removeWriteStream($stream)
|
||||
{
|
||||
$key = (int) $stream;
|
||||
$id = (int) $stream;
|
||||
|
||||
unset(
|
||||
$this->writeStreams[$key],
|
||||
$this->writeListeners[$key]
|
||||
$this->writeStreams[$id],
|
||||
$this->writeListeners[$id]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function removeStream($stream)
|
||||
{
|
||||
$this->removeReadStream($stream);
|
||||
$this->removeWriteStream($stream);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function addTimer($interval, callable $callback)
|
||||
public function addTimer($interval, $callback)
|
||||
{
|
||||
$timer = new Timer($this, $interval, $callback, false);
|
||||
|
||||
$this->timers->add($timer);
|
||||
|
||||
return $timer;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function addPeriodicTimer($interval, callable $callback)
|
||||
public function addPeriodicTimer($interval, $callback)
|
||||
{
|
||||
$timer = new Timer($this, $interval, $callback, true);
|
||||
|
||||
$this->timers->add($timer);
|
||||
|
||||
return $timer;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function cancelTimer(TimerInterface $timer)
|
||||
{
|
||||
$this->timers->cancel($timer);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isTimerActive(TimerInterface $timer)
|
||||
{
|
||||
return $this->timers->contains($timer);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function nextTick(callable $listener)
|
||||
protected function getNextEventTimeInMicroSeconds()
|
||||
{
|
||||
$this->nextTickQueue->add($listener);
|
||||
$nextEvent = $this->timers->getFirst();
|
||||
|
||||
if (null === $nextEvent) {
|
||||
return self::QUANTUM_INTERVAL;
|
||||
}
|
||||
|
||||
$currentTime = microtime(true);
|
||||
if ($nextEvent > $currentTime) {
|
||||
return ($nextEvent - $currentTime) * 1000000;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function futureTick(callable $listener)
|
||||
protected function sleepOnPendingTimers()
|
||||
{
|
||||
$this->futureTickQueue->add($listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function tick()
|
||||
{
|
||||
$this->nextTickQueue->tick();
|
||||
|
||||
$this->futureTickQueue->tick();
|
||||
|
||||
$this->timers->tick();
|
||||
|
||||
$this->waitForStreamActivity(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
$this->running = true;
|
||||
|
||||
while ($this->running) {
|
||||
$this->nextTickQueue->tick();
|
||||
|
||||
$this->futureTickQueue->tick();
|
||||
|
||||
$this->timers->tick();
|
||||
|
||||
// Next-tick or future-tick queues have pending callbacks ...
|
||||
if (!$this->running || !$this->nextTickQueue->isEmpty() || !$this->futureTickQueue->isEmpty()) {
|
||||
$timeout = 0;
|
||||
|
||||
// There is a pending timer, only block until it is due ...
|
||||
} elseif ($scheduledAt = $this->timers->getFirst()) {
|
||||
if (0 > $timeout = $scheduledAt - $this->timers->getTime()) {
|
||||
$timeout = 0;
|
||||
}
|
||||
|
||||
// The only possible event is stream activity, so wait forever ...
|
||||
} elseif ($this->readStreams || $this->writeStreams) {
|
||||
$timeout = null;
|
||||
|
||||
// There's nothing left to do ...
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
||||
$this->waitForStreamActivity($timeout * self::MICROSECONDS_PER_SECOND);
|
||||
if ($this->timers->isEmpty()) {
|
||||
$this->running = false;
|
||||
} else {
|
||||
// We use usleep() instead of stream_select() to emulate timeouts
|
||||
// since the latter fails when there are no streams registered for
|
||||
// read / write events. Blame PHP for us needing this hack.
|
||||
usleep($this->getNextEventTimeInMicroSeconds());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function runStreamSelect($block)
|
||||
{
|
||||
$read = $this->readStreams ?: null;
|
||||
$write = $this->writeStreams ?: null;
|
||||
$except = null;
|
||||
|
||||
if (!$read && !$write) {
|
||||
if ($block) {
|
||||
$this->sleepOnPendingTimers();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$timeout = $block ? $this->getNextEventTimeInMicroSeconds() : 0;
|
||||
|
||||
if (stream_select($read, $write, $except, 0, $timeout) > 0) {
|
||||
if ($read) {
|
||||
foreach ($read as $stream) {
|
||||
if (!isset($this->readListeners[(int) $stream])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$listener = $this->readListeners[(int) $stream];
|
||||
call_user_func($listener, $stream, $this);
|
||||
}
|
||||
}
|
||||
|
||||
if ($write) {
|
||||
foreach ($write as $stream) {
|
||||
if (!isset($this->writeListeners[(int) $stream])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$listener = $this->writeListeners[(int) $stream];
|
||||
call_user_func($listener, $stream, $this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function loop($block = true)
|
||||
{
|
||||
$this->timers->tick();
|
||||
$this->runStreamSelect($block);
|
||||
|
||||
return $this->running;
|
||||
}
|
||||
|
||||
public function tick()
|
||||
{
|
||||
return $this->loop(false);
|
||||
}
|
||||
|
||||
public function run()
|
||||
{
|
||||
$this->running = true;
|
||||
while ($this->loop());
|
||||
}
|
||||
|
||||
public function stop()
|
||||
{
|
||||
$this->running = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait/check for stream activity, or until the next timer is due.
|
||||
*/
|
||||
private function waitForStreamActivity($timeout)
|
||||
{
|
||||
$read = $this->readStreams;
|
||||
$write = $this->writeStreams;
|
||||
|
||||
$this->streamSelect($read, $write, $timeout);
|
||||
|
||||
foreach ($read as $stream) {
|
||||
$key = (int) $stream;
|
||||
|
||||
if (isset($this->readListeners[$key])) {
|
||||
call_user_func($this->readListeners[$key], $stream, $this);
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($write as $stream) {
|
||||
$key = (int) $stream;
|
||||
|
||||
if (isset($this->writeListeners[$key])) {
|
||||
call_user_func($this->writeListeners[$key], $stream, $this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Emulate a stream_select() implementation that does not break when passed
|
||||
* empty stream arrays.
|
||||
*
|
||||
* @param array &$read An array of read streams to select upon.
|
||||
* @param array &$write An array of write streams to select upon.
|
||||
* @param integer|null $timeout Activity timeout in microseconds, or null to wait forever.
|
||||
*
|
||||
* @return integer The total number of streams that are ready for read/write.
|
||||
*/
|
||||
protected function streamSelect(array &$read, array &$write, $timeout)
|
||||
{
|
||||
if ($read || $write) {
|
||||
$except = null;
|
||||
|
||||
return stream_select($read, $write, $except, $timeout === null ? null : 0, $timeout);
|
||||
}
|
||||
|
||||
usleep($timeout);
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue