Skip to content

Implemented some experimental event loops with nextTick() support. #234

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 24 commits into from
Dec 5, 2013
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
db41311
Implemented some experimental event loops with nextTick() support.
jmalloc Nov 13, 2013
cbe3664
Trying installion of ext-event in travis configuration.
jmalloc Nov 13, 2013
f0fb0af
Changed StreamSelectNextTickLoop to use existing Timers implementation.
jmalloc Nov 13, 2013
abbb05d
Removed AbstractNextTickLoop::streamKey()
jmalloc Nov 13, 2013
75b496a
Abstracted the actual next-tick queue into it's own class.
jmalloc Nov 13, 2013
35e4cd0
Reduced method dispatching somewhat.
jmalloc Nov 13, 2013
7fac0d3
Favour isset() over array_key_exists().
jmalloc Nov 13, 2013
514d05b
Removed NextTickLoopInterface, AbstractNextTickLoop and renamed Strea…
jmalloc Nov 14, 2013
85d0bcc
Various changes as per comments in PR.
jmalloc Nov 15, 2013
93da5ec
Fixed and added test-case for next-tick events added by timers.
jmalloc Nov 15, 2013
dc43f53
Removed some unnecessary left-overs.
jmalloc Nov 15, 2013
a8af7bc
Use status for unused parameters.
jmalloc Nov 15, 2013
18a00c7
Added nextTick() support to LibEventLoop (based off ExtEventLoop).
jmalloc Nov 18, 2013
3bba9e4
Renamed NextTick namespace to Tick + enable ExtEventLoop tests for Li…
jmalloc Nov 18, 2013
74131f7
Added nextTick() support to LibEvLoop.
jmalloc Nov 18, 2013
17c378f
Use 'inheritdoc' for methods from LoopInterface.
jmalloc Nov 21, 2013
7d7dd65
Code style.
jmalloc Nov 21, 2013
a8fe3cf
Added callable type-hint to LoopInterface, use SplQueue::isEmpty().
jmalloc Nov 21, 2013
0ac0305
Simplification of LibEvLoop.
jmalloc Nov 21, 2013
3ac92ee
Added @-operator error suppression to EventBase::loop() calls.
jmalloc Nov 21, 2013
87d2207
Code style.
jmalloc Nov 21, 2013
cae3165
Add 1µs minimum interval to Timer, and remove Timers::MIN_RESOLUTION.
jmalloc Nov 22, 2013
c0cd613
Changed protected methods in event-loop implementations to private.
jmalloc Dec 1, 2013
edc337e
Removed ExtEventLoop
jmalloc Dec 4, 2013
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Implemented some experimental event loops with nextTick() support.
* ExtEventLoop - based on the ext-event PHP extension
* StreamSelectNextTickLoop - based on stream_select
  • Loading branch information
jmalloc committed Nov 13, 2013
commit db41311c7d380a003d3f421d7033555347791c9d
180 changes: 180 additions & 0 deletions src/React/EventLoop/AbstractNextTickLoop.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
<?php

namespace React\EventLoop;

use React\EventLoop\Timer\Timer;
use React\EventLoop\Timer\TimerInterface;
use SplQueue;

/**
* Common functionality for event loops that implement NextTickLoopInterface.
*/
abstract class AbstractNextTickLoop implements NextTickLoopInterface
{
private $nextTickQueue;
private $explicitlyStopped;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just $stop would do, IMHO.


public function __construct()
{
$this->nextTickQueue = new SplQueue;
$this->explicitlyStopped = false;
}

/**
* Enqueue a callback to be invoked once after the given interval.
*
* The execution order of timers scheduled to execute at the same time is
* not guaranteed.
*
* @param numeric $interval The number of seconds to wait before execution.
* @param callable $callback The callback to invoke.
*
* @return TimerInterface
*/
public function addTimer($interval, $callback)
{
$timer = new Timer($this, $interval, $callback, false);

$this->scheduleTimer($timer);

return $timer;
}

/**
* Enqueue a callback to be invoked repeatedly after the given interval.
*
* The execution order of timers scheduled to execute at the same time is
* not guaranteed.
*
* @param numeric $interval The number of seconds to wait before execution.
* @param callable $callback The callback to invoke.
*
* @return TimerInterface
*/
public function addPeriodicTimer($interval, $callback)
{
$timer = new Timer($this, $interval, $callback, true);

$this->scheduleTimer($timer);

return $timer;
}

/**
* Schedule a callback to be invoked on the next tick of the event loop.
*
* Callbacks are guaranteed to be executed in the order they are enqueued,
* before any timer or stream events.
*
* @param callable $listner The callback to invoke.
*/
public function nextTick(callable $listener)
{
$this->nextTickQueue->enqueue($listener);
}

/**
* Perform a single iteration of the event loop.
*/
public function tick()
{
$this->tickLogic(false);
}

/**
* Run the event loop until there are no more tasks to perform.
*/
public function run()
{
$this->explicitlyStopped = false;

while ($this->isRunning()) {
$this->tickLogic(true);
}
}

/**
* Instruct a running event loop to stop.
*/
public function stop()
{
$this->explicitlyStopped = true;
}

/**
* Invoke all callbacks in the next-tick queue.
*/
protected function flushNextTickQueue()
{
while ($this->nextTickQueue->count()) {
call_user_func(
$this->nextTickQueue->dequeue(),
$this
);
}
}

/**
* Check if there is any pending work to do.
*
* @return boolean
*/
protected function isRunning()
{
// The loop has been explicitly stopped and should exit ...
if ($this->explicitlyStopped) {
return false;

// The next tick queue has items on it ...
} elseif ($this->nextTickQueue->count() > 0) {
return true;
}

return !$this->isEmpty();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seriously nitpicking here, but I think the logic behind isEmpty() is flawed. We leave the actual implementation of isEmpty() to the concrete class for obvious reasons but the next tick queue should be considered as part of what makes an event loop empty or not, which is not the case here (and currently concrete classes have no access to the next tick queue).

That's one reason why I don't like much the strictness an abstract class enforces upon us.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah it needed a better name, but ... the abstract class has been removed entirely in the most recent push :)

}

/**
* Perform the low-level tick logic.
*/
protected function tickLogic($blocking)
{
$this->flushNextTickQueue();

$this->flushEvents(
$blocking && 0 === $this->nextTickQueue->count()
);
}

/**
* Get a key that can be used to identify a stream resource.
*
* @param string $stream
*
* @return integer|string
*/
protected function streamKey($stream)
{
return (int) $stream;
}

/**
* Schedule a timer for execution.
*
* @param TimerInterface $timer
*/
abstract protected function scheduleTimer(TimerInterface $timer);

/**
* Flush any timer and IO events.
*
* @param boolean $blocking True if loop should block waiting for next event.
*/
abstract protected function flushEvents($blocking);

/**
* Check if the loop has any pending timers or streams.
*
* @return boolean
*/
abstract protected function isEmpty();
}
Loading
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy