Initial commit
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
<?php
|
||||
|
||||
namespace NoccyLabs\Ipc\Interop\Async;
|
||||
|
||||
use NoccyLabs\Ipc\Signal\SignalHandler;
|
||||
|
||||
|
||||
/**
|
||||
* Simple second-granularity timer for asynchronous events
|
||||
*
|
||||
*/
|
||||
class Timer
|
||||
{
|
||||
private static $timers = null;
|
||||
|
||||
private $callback;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param callable $callback
|
||||
*/
|
||||
public function __construct(callable $callback)
|
||||
{
|
||||
$this->callback = $callback;
|
||||
$this->seconds = $seconds;
|
||||
self::registerTimer($this->callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
self::clearTimer($this->callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a timer callback function
|
||||
*
|
||||
* @param callable $timer
|
||||
* @return void
|
||||
*/
|
||||
private static function registerTimer(callable $timer)
|
||||
{
|
||||
if (self::$timers === null) {
|
||||
$handler = new SignalHandler(SIGALRM, [ __CLASS__."::onSignal" ]);
|
||||
pcntl_alarm(1);
|
||||
}
|
||||
self::$timers[] = $timer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a timer callback function
|
||||
*
|
||||
* @param callable $timer
|
||||
* @return void
|
||||
*/
|
||||
private static function clearTimer(callable $timer)
|
||||
{
|
||||
self::$timers = array_filter(self::$timers, function ($t) use ($timer) {
|
||||
return $t !== $timer;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle signals when the alarm fires
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function onSignal()
|
||||
{
|
||||
foreach (self::$timers as $timer) {
|
||||
call_user_func($timer);
|
||||
}
|
||||
pcntl_alarm(1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace NoccyLabs\Ipc\Interop\Channel;
|
||||
|
||||
|
||||
interface ChannelInterface
|
||||
{
|
||||
public function isOpen():bool;
|
||||
|
||||
public function receive();
|
||||
|
||||
public function send($data);
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
namespace NoccyLabs\Ipc\Interop\Channel;
|
||||
|
||||
|
||||
class StreamChannel implements ChannelInterface
|
||||
{
|
||||
protected $stream;
|
||||
|
||||
public function __construct($stream)
|
||||
{
|
||||
if (!is_resource($stream)) {
|
||||
if (!is_string($stream)) {
|
||||
throw new \LogicException("Invalid stream");
|
||||
}
|
||||
$stream = stream_socket_client($stream, $errno, $errstr);
|
||||
if (!$stream) {
|
||||
throw new \RuntimeException(sprintf("%d %s", $errno, $errstr));
|
||||
}
|
||||
}
|
||||
|
||||
$this->stream = $stream;
|
||||
|
||||
$this->isOpen();
|
||||
}
|
||||
|
||||
public function send($data)
|
||||
{
|
||||
fwrite($this->stream, json_encode($data)."\0");
|
||||
}
|
||||
|
||||
public function receive()
|
||||
{
|
||||
$buf = fread($this->stream, 8192);
|
||||
|
||||
return json_decode(rtrim($buf, "\0"));
|
||||
}
|
||||
|
||||
public function isOpen(): bool
|
||||
{
|
||||
return is_resource($this->stream);
|
||||
}
|
||||
|
||||
public static function createPair()
|
||||
{
|
||||
$fd = stream_socket_pair(STREAM_PF_UNIX, STREAM_SOCK_STREAM, STREAM_IPPROTO_IP);
|
||||
|
||||
return [
|
||||
new StreamChannel($fd[0]),
|
||||
new StreamChannel($fd[1])
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user