Skip to content

Instantly share code, notes, and snippets.

@cameronjacobson
Created November 16, 2012 13:52
Show Gist options
  • Save cameronjacobson/4087515 to your computer and use it in GitHub Desktop.
Save cameronjacobson/4087515 to your computer and use it in GitHub Desktop.
early stages of a php libevent project (inspired by reactphp/react)
<?php
include('EventTrait.php');
class EventLoop
{
use EventTrait;
private $base;
private $events;
private $deleted;
public function __construct(){
$this->base = event_base_new();
$this->deleted = new SplQueue();
$this->iteratorMode = SplDoublyLinkedList::IT_MODE_FIFO | SplDoublyLinkedList::IT_MODE_DELETE;
$this->deleted->setIteratorMode($this->iteratorMode);
}
public function setTimeout(callable $callback, $seconds){
$this->setTimer($callback, $seconds);
}
public function setInterval(callable $callback, $seconds){
$this->setTimer($callback, $seconds, true);
}
protected function setTimer($callback,$seconds,$persist = false){
$event = $this->createEvent();
$event->callback = $callback;
$event->seconds = $seconds;
$event->persist = $persist;
$cb = function() use ($event) {
call_user_func($event->callback);
if($event->persist){
$this->dispatchEvent($event);
}
else{
event_del($event->resource);
$this->deleted->enqueue($event->hash);
}
};
event_timer_set($event->resource, $cb);
event_base_set($event->resource, $this->base);
$this->dispatchEvent($event);
}
protected function dispatchEvent($event){
$seconds = isset($event->seconds) ? abs($event->seconds) * 1000000 : -1;
event_add($event->resource,$seconds);
}
protected function createEvent(){
if(count($this->deleted) > 0){
$deleted = $this->deleted->dequeue();
event_free($this->events[$deleted]->resource);
unset($this->events[$deleted]);
}
$hash = spl_object_hash($event = new stdClass());
$event->resource = event_new();
$event->hash = $hash;
$this->events[$hash] = $event;
return $event;
}
public function run(){
event_base_loop($this->base);
}
public function stop(){
event_base_loopexit($this->base);
}
}
<?php
trait EventTrait
{
private $observers;
private $once;
private $iteratorMode;
public function __construct(){
$this->once = array();
}
public function on($eventName, $callback) {
$this->observers[$eventName][] = function($arguments) use ($callback) {
return function() use($callback,$arguments){
call_user_func($callback,$arguments);
};
};
}
public function emit($eventName,$arguments = array()){
if(!empty($this->observers[$eventName])){
foreach($this->observers[$eventName] as $func){
$this->setTimeout($func($arguments),0);
}
}
while(count($this->once[$eventName]) > 0){
$func = $this->once[$eventName]->dequeue();
$this->setTimeout($func($arguments),0);
}
}
public function once($eventName, $callback) {
if(empty($this->once[$eventName])){
$this->once[$eventName] = new SplQueue();
$this->once[$eventName]->setIteratorMode($this->iteratorMode);
}
$cb = function($arguments) use($callback) {
return function() use($callback,$arguments){
call_user_func($callback,$arguments);
};
};
$this->once[$eventName]->enqueue($cb);
}
public function removeListener(){
}
public function removeAllListeners($eventName){
if ($eventName !== null) {
unset($this->listeners[$eventName]);
} else {
$this->listeners = array();
}
}
public function listeners($eventName){
return $this->observers[$eventName] ?: array();
}
}
<?php
include('EventLoop.php');
$app = new EventLoop();
$closure = function($value) use($app) {
$app->setInterval(function(){},0.01);
return function() use($value){
echo $value.PHP_EOL;
};
};
$app->setTimeout($closure('timeout'),1);
$app->setInterval($closure('interval'),0.5);
$app->setInterval(function() use ($app) {
echo 'MEMORY: '.memory_get_usage(true).PHP_EOL;
},2);
$app->run();
<?php
include('EventLoop.php');
$app = new EventLoop();
$app->on('blah',function($args){
print_r($args);
echo 'blah'.PHP_EOL;
});
$app->once('blah',function($args){
print_r($args);
echo 'blah'.PHP_EOL;
});
$app->emit('blah',array('blah','blah2'));
$app->emit('blah',array('blah22','blah33'));
$app->run();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment