Skip to content

Commit

Permalink
Add await/async function
Browse files Browse the repository at this point in the history
  • Loading branch information
toby7002 committed Sep 27, 2023
1 parent ef6d8be commit 293912d
Show file tree
Hide file tree
Showing 10 changed files with 754 additions and 1 deletion.
41 changes: 41 additions & 0 deletions src/thebigcrafter/Hydrogen/Hydrogen.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@

use pocketmine\plugin\Plugin;
use pocketmine\Server;
use thebigcrafter\Hydrogen\future\Future;
use thebigcrafter\Hydrogen\future\FutureState;
use thebigcrafter\Hydrogen\tasks\CheckUpdatesTask;

class Hydrogen {
Expand All @@ -23,4 +25,43 @@ class Hydrogen {
public static function checkForUpdates(Plugin $plugin) : void {
Server::getInstance()->getAsyncPool()->submitTask(new CheckUpdatesTask($plugin->getName(), $plugin->getDescription()->getVersion()));
}

/**
* Creates a new fiber asynchronously using the given closure, returning a Future that is completed with the
* eventual return value of the passed function or will fail if the closure throws an exception.
*
* @template T
*
* @param \Closure(...):T $closure
* @param mixed ...$args Arguments forwarded to the closure when starting the fiber.
*
* @return Future<T>
*/
public static function async(\Closure $closure, mixed ...$args) : Future

Check failure on line 40 in src/thebigcrafter/Hydrogen/Hydrogen.php

View workflow job for this annotation

GitHub Actions / PHPStan analysis (ubuntu-latest, 8.1)

PHPDoc tag @param has invalid value (\Closure(...):T $closure): Unexpected token "(", expected variable at offset 255

Check failure on line 40 in src/thebigcrafter/Hydrogen/Hydrogen.php

View workflow job for this annotation

GitHub Actions / PHPStan analysis (ubuntu-latest, 8.1)

Template type T of method thebigcrafter\Hydrogen\Hydrogen::async() is not referenced in a parameter.
{
static $run = null;

$run ??= static function (FutureState $state, \Closure $closure, array $args) : void {
$s = $state;
$c = $closure;

/* Null function arguments so an exception thrown from the closure does not contain the FutureState object
* in the stack trace, which would create a circular reference, preventing immediate garbage collection */
$state = $closure = null;

try {
// Clear $args to allow garbage collection of arguments during fiber execution
$s->complete($c(...$args, ...($args = [])));
} catch (\Throwable $exception) {
$s->error($exception);
}
};

$state = new FutureState();

EventLoop::queue($run, $state, $closure, $args);

return new Future($state);
}

}
47 changes: 47 additions & 0 deletions src/thebigcrafter/Hydrogen/exceptions/Cancellation.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<?php

/*
* This file is part of Hydrogen.
* (c) thebigcrafter <[email protected]>
* This source file is subject to the Apache-2.0 license that is bundled
* with this source code in the file LICENSE.
*/

declare(strict_types=1);

namespace thebigcrafter\Hydrogen\exceptions;

interface Cancellation
{
/**
* Subscribes a new handler to be invoked on a cancellation request.
*
* This handler might be invoked immediately in case the cancellation has already been requested. Any unhandled
* exceptions will be thrown into the event loop.
*
* @param \Closure(CancelledException) $callback Callback to be invoked on a cancellation request. Will receive a
* `CancelledException` as first argument that may be used to fail the operation.
*
* @return string Identifier that can be used to cancel the subscription.
*/
public function subscribe(\Closure $callback) : string;

Check failure on line 27 in src/thebigcrafter/Hydrogen/exceptions/Cancellation.php

View workflow job for this annotation

GitHub Actions / PHPStan analysis (ubuntu-latest, 8.1)

PHPDoc tag @param has invalid value (\Closure(CancelledException) $callback Callback to be invoked on a cancellation request. Will receive a `CancelledException` as first argument that may be used to fail the operation.): Unexpected token "(", expected variable at offset 265

/**
* Unsubscribes a previously registered handler.
*
* The handler will no longer be called as long as this method isn't invoked from a subscribed callback.
*/
public function unsubscribe(string $id) : void;

/**
* Returns whether cancellation has been requested yet.
*/
public function isRequested() : bool;

/**
* Throws the `CancelledException` if cancellation has been requested, otherwise does nothing.
*
* @throws CancelledException
*/
public function throwIfRequested() : void;

Check failure on line 46 in src/thebigcrafter/Hydrogen/exceptions/Cancellation.php

View workflow job for this annotation

GitHub Actions / PHPStan analysis (ubuntu-latest, 8.1)

PHPDoc tag @throws with type thebigcrafter\Hydrogen\exceptions\CancelledException is not subtype of Throwable
}
35 changes: 35 additions & 0 deletions src/thebigcrafter/Hydrogen/exceptions/NullCancellation.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

/*
* This file is part of Hydrogen.
* (c) thebigcrafter <[email protected]>
* This source file is subject to the Apache-2.0 license that is bundled
* with this source code in the file LICENSE.
*/

declare(strict_types=1);

namespace thebigcrafter\Hydrogen\exceptions;

final class NullCancellation implements Cancellation
{
public function subscribe(\Closure $callback) : string
{
return "null-cancellation";
}

public function unsubscribe(string $id) : void
{
// nothing to do
}

public function isRequested() : bool
{
return false;
}

public function throwIfRequested() : void
{
// nothing to do
}
}
Loading

0 comments on commit 293912d

Please sign in to comment.