1
0
Fork 0
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:
Afterster 2014-04-13 08:58:34 +02:00
parent d3f01a3bc7
commit 7f82bea13e
50 changed files with 608 additions and 1937 deletions

View file

@ -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;
}
}