Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
64 changes: 59 additions & 5 deletions src/Loop.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,36 @@ final class Loop
{
use Registry;

/**
* @var LoopDriverFactory
*/
private static $factory = null;

/**
* @var LoopDriver
*/
private static $driver = null;

/**
* @var bool
*/
private static $running = false;

/**
* Set the factory to be used to create a driver if none is passed to
* self::execute. A default driver will be created if none is running
* to support synchronous waits in traditional applications.
*/
public static function setFactory(LoopDriverFactory $factory = null)
{
self::$factory = $factory;

if (!self::$running) {
self::$driver = self::createDriver();
self::$registry = [];
}
}

/**
* Execute a callback within the scope of an event loop driver.
*
Expand All @@ -19,13 +44,16 @@ final class Loop
*
* @return void
*/
public static function execute(callable $callback, LoopDriver $driver)
public static function execute(callable $callback, LoopDriver $driver = null)
{
$previousDriver = self::$driver;
$previousRegistry = self::$registry;
$previousDriver = self::$driver;

$driver = $driver ?: self::createDriver();

self::$driver = $driver;
self::$registry = [];
self::$running = true;

try {
$callback();
Expand All @@ -34,9 +62,31 @@ public static function execute(callable $callback, LoopDriver $driver)
} finally {
self::$driver = $previousDriver;
self::$registry = $previousRegistry;
self::$running = false;
}
}

/**
* Create a new driver if a factory is present, otherwise throw.
*
* @throws \LogicException if no factory is set or no driver returned from factory
*/
private static function createDriver()
{
if (self::$factory === null) {
throw new \LogicException("No loop driver factory set; Either pass a driver to Loop::execute or set a factory.");
}

$driver = self::$factory->create();

if (!$driver instanceof LoopDriver) {
$type = is_object($driver) ? "an instance of " . get_class($driver) : gettype($driver);
throw new \LogicException("Loop driver factory returned {$type}, but must return an instance of LoopDriver.");
}

return $driver;
}

/**
* Retrieve the event loop driver that is in scope.
*
Expand All @@ -45,7 +95,7 @@ public static function execute(callable $callback, LoopDriver $driver)
public static function get()
{
if (null === self::$driver) {
throw new \RuntimeException('Not within the scope of an event loop driver');
throw new \RuntimeException('Missing driver; Neither in Loop::execute nor factory set.');
}

return self::$driver;
Expand Down Expand Up @@ -232,12 +282,16 @@ public static function setErrorHandler(callable $callback = null)
*
* @return bool
*/
public static function supports($feature) {
public static function supports($feature)
{
return self::get()->supports($feature);
}

/**
* Disable construction as this is a static class.
*/
private function __construct() {}
private function __construct()
{
// intentionally left blank
}
}
13 changes: 13 additions & 0 deletions src/LoopDriverFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

namespace Interop\Async;

interface LoopDriverFactory
{
/**
* Create a new event loop driver instance.
*
* @return LoopDriver
*/
public function create();
}