mirror of
https://github.com/danog/asyncConstruct.git
synced 2024-11-26 10:44:38 +01:00
First commit
This commit is contained in:
commit
ef20c2ef10
1
.github/FUNDING.yml
vendored
Normal file
1
.github/FUNDING.yml
vendored
Normal file
@ -0,0 +1 @@
|
||||
github: danog
|
49
.github/workflows/main.yml
vendored
Normal file
49
.github/workflows/main.yml
vendored
Normal file
@ -0,0 +1,49 @@
|
||||
name: build
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
jobs:
|
||||
run:
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest]
|
||||
php-versions: ["7.1", "7.2", "7.3", "7.4"]
|
||||
name: PHP ${{ matrix.php-versions }} Test on ${{ matrix.os }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Setup PHP
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: ${{ matrix.php-versions }}
|
||||
extensions: mbstring, intl, sockets
|
||||
coverage: xdebug
|
||||
|
||||
- name: Check environment
|
||||
run: |
|
||||
php --version
|
||||
composer --version
|
||||
|
||||
- name: Get composer cache directory
|
||||
id: composercache
|
||||
run: echo "::set-output name=dir::$(composer config cache-files-dir)"
|
||||
|
||||
- name: Cache dependencies
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ${{ steps.composercache.outputs.dir }}
|
||||
key: ${{ matrix.os }}-composer-${{ matrix.php-versions }}-${{ hashFiles('**/composer.lock') }}
|
||||
restore-keys: ${{ matrix.os }}-composer-${{ matrix.php-versions }}-
|
||||
|
||||
- name: Install dependencies
|
||||
run: composer install --prefer-dist
|
||||
|
||||
- name: Run tests
|
||||
env:
|
||||
PHP_CS_FIXER_IGNORE_ENV: 1
|
||||
run: |
|
||||
vendor/bin/phpunit --coverage-text --coverage-clover build/logs/clover.xml
|
||||
vendor/bin/php-cs-fixer --diff --dry-run -v fix
|
||||
vendor/bin/psalm
|
7
.gitignore
vendored
Normal file
7
.gitignore
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
.vscode
|
||||
build
|
||||
composer.lock
|
||||
phpunit.xml
|
||||
vendor
|
||||
.php_cs.cache
|
||||
coverage
|
13
.php_cs.dist
Normal file
13
.php_cs.dist
Normal file
@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
$config = new Amp\CodeStyle\Config();
|
||||
$config->getFinder()
|
||||
->in(__DIR__ . '/examples')
|
||||
->in(__DIR__ . '/lib')
|
||||
->in(__DIR__ . '/test');
|
||||
|
||||
$cacheDir = getenv('TRAVIS') ? getenv('HOME') . '/.php-cs-fixer' : __DIR__;
|
||||
|
||||
$config->setCacheFile($cacheDir . '/.php_cs.cache');
|
||||
|
||||
return $config;
|
7
LICENSE
Normal file
7
LICENSE
Normal file
@ -0,0 +1,7 @@
|
||||
Copyright 2019-2020 Daniil Gentili
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
74
README.md
Normal file
74
README.md
Normal file
@ -0,0 +1,74 @@
|
||||
# AsyncConstruct
|
||||
|
||||
![Build status](https://github.com/danog/asyncConstruct/workflows/build/badge.svg)
|
||||
[![codecov](https://codecov.io/gh/danog/asyncConstruct/branch/master/graph/badge.svg)](https://codecov.io/gh/danog/asyncConstruct)
|
||||
![License](https://img.shields.io/badge/license-MIT-blue.svg)
|
||||
|
||||
`danog/asyncConstruct` provides async class constructor and wakeup functions for AMPHP.
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
composer require danog/async-construct
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
* Async
|
||||
* [AsyncConstruct](#AsyncConstruct)
|
||||
* [AsyncWakeup](#AsyncWakeup)
|
||||
* Blocking
|
||||
* [BlockingConstruct](#BlockingConstruct)
|
||||
* [BlockingWakeup](#BlockingWakeup)
|
||||
|
||||
### AsyncConstruct
|
||||
|
||||
[Example](https://github.com/danog/asyncConstruct/blob/master/examples/AsyncConstruct.php)
|
||||
|
||||
Simply `use` this trait in your class, and define a `__construct_async` async method.
|
||||
The trait will automatically run the async method on construction, and expose a set of APIs to wait on the result of the constructor for initialization.
|
||||
|
||||
### init()
|
||||
|
||||
Will blockingly wait for execution of the async constructor, returning its return value.
|
||||
|
||||
### initAsynchronously()
|
||||
|
||||
Will return a promise that, when `yield`ed, will wait for and return the return value of the constructor.
|
||||
|
||||
### inited()
|
||||
|
||||
Returns a boolean, indicating whether the class was initialized or not.
|
||||
|
||||
|
||||
### BlockingConstruct
|
||||
|
||||
[Example](https://github.com/danog/asyncConstruct/blob/master/examples/BlockingConstruct.php)
|
||||
|
||||
Exactly like [AsyncConstruct], except that the blocking `init()` function will be automatically called on construction.
|
||||
|
||||
### AsyncWakeup
|
||||
|
||||
[Example](https://github.com/danog/asyncConstruct/blob/master/examples/AsyncWakeup.php)
|
||||
|
||||
Simply `use` this trait in your class, and define a `__wakeup_async` async method.
|
||||
The trait will automatically run the async method on deserialization, and expose a set of APIs to wait on the result of the wakeup function for re-initialization.
|
||||
|
||||
### wakeup()
|
||||
|
||||
Will blockingly wait for execution of the async wakeup function, returning its return value.
|
||||
|
||||
### wakeupAsynchronously()
|
||||
|
||||
Will return a promise that, when `yield`ed, will wait for and return the return value of the wakeup function.
|
||||
|
||||
### wokenUp()
|
||||
|
||||
Returns a boolean, indicating whether the class was initialized or not.
|
||||
|
||||
|
||||
### BlockingWakeup
|
||||
|
||||
[Example](https://github.com/danog/asyncConstruct/blob/master/examples/BlockingWakeup.php)
|
||||
|
||||
Exactly like [AsyncWakeup], except that the blocking `wakeup()` function will be automatically called on wakeup.
|
48
composer.json
Normal file
48
composer.json
Normal file
@ -0,0 +1,48 @@
|
||||
{
|
||||
"name": "danog/async-construct",
|
||||
"description": "Async class constructor and wakeup functions for AMPHP.",
|
||||
"keywords": [
|
||||
"asynchronous",
|
||||
"async",
|
||||
"concurrent",
|
||||
"multi-threading",
|
||||
"multi-processing"
|
||||
],
|
||||
"homepage": "https://github.com/danog/asyncConstruct",
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Daniil Gentili",
|
||||
"email": "daniil@daniil.it"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=7.1",
|
||||
"amphp/amp": "^2"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^7 | ^8 | ^9",
|
||||
"amphp/phpunit-util": "^1.3",
|
||||
"amphp/php-cs-fixer-config": "dev-master",
|
||||
"vimeo/psalm": "dev-master"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"danog\\": "lib"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"danog\\Test\\": "test"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"check": [
|
||||
"@cs",
|
||||
"@test"
|
||||
],
|
||||
"cs": "php-cs-fixer fix -v --diff --dry-run",
|
||||
"cs-fix": "php-cs-fixer fix -v --diff",
|
||||
"test": "phpdbg -qrr -dzend.assertions=1 -dassert.exception=1 ./vendor/bin/phpunit --coverage-text"
|
||||
}
|
||||
}
|
34
examples/async.php
Normal file
34
examples/async.php
Normal file
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
use Amp\Loop;
|
||||
use danog\AsyncConstruct;
|
||||
|
||||
use function Amp\delay;
|
||||
|
||||
require 'vendor/autoload.php';
|
||||
|
||||
class AsyncTest
|
||||
{
|
||||
use AsyncConstruct;
|
||||
/**
|
||||
* Async constructor function.
|
||||
*
|
||||
* Typically, one would establish an async AMP database connection here, or do some other async stuff.
|
||||
*
|
||||
* @param integer $delay Constructor delay
|
||||
*
|
||||
* @return \Generator
|
||||
*/
|
||||
protected function __construct_async(int $delay): \Generator
|
||||
{
|
||||
yield delay($delay);
|
||||
echo "Inited after $delay milliseconds!".PHP_EOL;
|
||||
}
|
||||
}
|
||||
|
||||
Loop::run(function () {
|
||||
echo "Before starting constructor".PHP_EOL;
|
||||
$test = new AsyncTest(1000);
|
||||
echo "Started constructor, waiting...".PHP_EOL;
|
||||
yield $test->initAsynchronously();
|
||||
});
|
48
examples/asyncWakeup.php
Normal file
48
examples/asyncWakeup.php
Normal file
@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
use Amp\Loop;
|
||||
use danog\AsyncWakeup;
|
||||
|
||||
use function Amp\delay;
|
||||
|
||||
require 'vendor/autoload.php';
|
||||
|
||||
class AsyncWakeupTest
|
||||
{
|
||||
use AsyncWakeup;
|
||||
/**
|
||||
* Time to wait for wakeup.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $delay;
|
||||
/**
|
||||
* Constructor function.
|
||||
*
|
||||
* @param integer $delay
|
||||
*/
|
||||
public function __construct(int $delay)
|
||||
{
|
||||
$this->delay = $delay;
|
||||
}
|
||||
/**
|
||||
* Async wakeup function.
|
||||
*
|
||||
* Typically, one would re-establish an async AMP database connection here, or do some other async stuff.
|
||||
*
|
||||
* @return \Generator
|
||||
*/
|
||||
protected function __wakeup_async(): \Generator
|
||||
{
|
||||
yield delay($this->delay);
|
||||
echo "Woke up after {$this->delay} milliseconds!".PHP_EOL;
|
||||
}
|
||||
}
|
||||
|
||||
Loop::run(function () {
|
||||
$test = new AsyncWakeupTest(1000);
|
||||
$test = \serialize($test);
|
||||
$test = \unserialize($test);
|
||||
echo "Deserialized, waiting asynchronously...".PHP_EOL;
|
||||
yield $test->wakeupAsynchronously();
|
||||
});
|
33
examples/blocking.php
Normal file
33
examples/blocking.php
Normal file
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
use Amp\Loop;
|
||||
use danog\BlockingConstruct;
|
||||
|
||||
use function Amp\delay;
|
||||
|
||||
require 'vendor/autoload.php';
|
||||
|
||||
class BlockingTest
|
||||
{
|
||||
use BlockingConstruct;
|
||||
/**
|
||||
* Async constructor function.
|
||||
*
|
||||
* Typically, one would establish an async AMP database connection here, or do some other async stuff.
|
||||
*
|
||||
* @param integer $delay Constructor delay
|
||||
*
|
||||
* @return \Generator
|
||||
*/
|
||||
protected function __construct_async(int $delay): \Generator
|
||||
{
|
||||
yield delay($delay);
|
||||
echo "Inited after $delay milliseconds!".PHP_EOL;
|
||||
}
|
||||
}
|
||||
|
||||
Loop::run(function () {
|
||||
echo "Before starting constructor".PHP_EOL;
|
||||
$test = new BlockingTest(1000);
|
||||
echo "Started constructor!".PHP_EOL;
|
||||
});
|
47
examples/blockingWakeup.php
Normal file
47
examples/blockingWakeup.php
Normal file
@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
use Amp\Loop;
|
||||
use danog\BlockingWakeup;
|
||||
|
||||
use function Amp\delay;
|
||||
|
||||
require 'vendor/autoload.php';
|
||||
|
||||
class BlockingWakeupTest
|
||||
{
|
||||
use BlockingWakeup;
|
||||
/**
|
||||
* Time to wait for wakeup.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $delay;
|
||||
/**
|
||||
* Constructor function.
|
||||
*
|
||||
* @param integer $delay
|
||||
*/
|
||||
public function __construct(int $delay)
|
||||
{
|
||||
$this->delay = $delay;
|
||||
}
|
||||
/**
|
||||
* Async wakeup function.
|
||||
*
|
||||
* Typically, one would re-establish an async AMP database connection here, or do some other async stuff.
|
||||
*
|
||||
* @return \Generator
|
||||
*/
|
||||
protected function __wakeup_async(): \Generator
|
||||
{
|
||||
yield delay($this->delay);
|
||||
echo "Woke up after {$this->delay} milliseconds!".PHP_EOL;
|
||||
}
|
||||
}
|
||||
|
||||
Loop::run(function () {
|
||||
$test = new BlockingWakeupTest(1000);
|
||||
$test = \serialize($test);
|
||||
echo "Deserializing...".PHP_EOL;
|
||||
$test = \unserialize($test);
|
||||
});
|
105
lib/AsyncConstruct.php
Normal file
105
lib/AsyncConstruct.php
Normal file
@ -0,0 +1,105 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Async constructor trait.
|
||||
*
|
||||
* @author Daniil Gentili <daniil@daniil.it>
|
||||
* @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
|
||||
* @license https://opensource.org/licenses/MIT MIT
|
||||
*/
|
||||
|
||||
namespace danog;
|
||||
|
||||
use Amp\Coroutine;
|
||||
use Amp\Promise;
|
||||
use Amp\Success;
|
||||
|
||||
use function Amp\Promise\wait;
|
||||
|
||||
/**
|
||||
* Async constructor trait.
|
||||
*
|
||||
* Manages asynchronous construction of async classes
|
||||
*
|
||||
* @author Daniil Gentili <daniil@daniil.it>
|
||||
*/
|
||||
trait AsyncConstruct
|
||||
{
|
||||
/**
|
||||
* Async init promise.
|
||||
*
|
||||
* @var ?Promise
|
||||
*/
|
||||
private $asyncInitPromise;
|
||||
/**
|
||||
* Constructor function.
|
||||
*
|
||||
* @param mixed ...$params Parameters
|
||||
*/
|
||||
public function __construct(...$params)
|
||||
{
|
||||
if (\method_exists($this, '__construct_async')) {
|
||||
$this->setInitPromise($this->__construct_async(...$params));
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Set init promise.
|
||||
*
|
||||
* @param Promise|\Generator $promise Promise
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function setInitPromise($promise): void
|
||||
{
|
||||
$this->asyncInitPromise = $promise instanceof \Generator ? new Coroutine($promise) : $promise;
|
||||
$this->asyncInitPromise->onResolve(
|
||||
function (?\Throwable $error, $result): void {
|
||||
$this->asyncInitPromise = null;
|
||||
}
|
||||
);
|
||||
}
|
||||
/**
|
||||
* Blockingly init.
|
||||
*
|
||||
* @return mixed Resolves with the result of the constructor or null
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
if ($this->asyncInitPromise) {
|
||||
return wait($this->asyncInitPromise);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
/**
|
||||
* Asynchronously init.
|
||||
*
|
||||
* @return Promise<mixed|null> Resolves with the result of the constructor or null
|
||||
*/
|
||||
public function initAsynchronously(): Promise
|
||||
{
|
||||
if ($this->asyncInitPromise) {
|
||||
return $this->asyncInitPromise;
|
||||
}
|
||||
return new Success();
|
||||
}
|
||||
/**
|
||||
* Check if we've already inited.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function inited(): bool
|
||||
{
|
||||
return !$this->asyncInitPromise;
|
||||
}
|
||||
/**
|
||||
* Mark instance as (de)inited forcefully.
|
||||
*
|
||||
* @param boolean $inited Whether to mark the instance as inited or deinited
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function forceInit(bool $inited): void
|
||||
{
|
||||
$this->asyncInitPromise = $inited ? null : new Success(null);
|
||||
}
|
||||
}
|
103
lib/AsyncWakeup.php
Normal file
103
lib/AsyncWakeup.php
Normal file
@ -0,0 +1,103 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Async wakeup trait.
|
||||
*
|
||||
* @author Daniil Gentili <daniil@daniil.it>
|
||||
* @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
|
||||
* @license https://opensource.org/licenses/MIT MIT
|
||||
*/
|
||||
|
||||
namespace danog;
|
||||
|
||||
use Amp\Coroutine;
|
||||
use Amp\Promise;
|
||||
use Amp\Success;
|
||||
|
||||
use function Amp\Promise\wait;
|
||||
|
||||
/**
|
||||
* Async wakeup trait.
|
||||
*
|
||||
* Manages asynchronous wakeup of async classes
|
||||
*
|
||||
* @author Daniil Gentili <daniil@daniil.it>
|
||||
*/
|
||||
trait AsyncWakeup
|
||||
{
|
||||
/**
|
||||
* Async wakeup promise.
|
||||
*
|
||||
* @var ?Promise
|
||||
*/
|
||||
private $asyncWakeupPromise;
|
||||
/**
|
||||
* Wakeup function.
|
||||
*/
|
||||
public function __wakeup(): void
|
||||
{
|
||||
if (\method_exists($this, '__wakeup_async')) {
|
||||
$this->setWakeupPromise($this->__wakeup_async());
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Set wakeup promise.
|
||||
*
|
||||
* @param Promise|\Generator $promise Promise
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function setWakeupPromise($promise): void
|
||||
{
|
||||
$this->asyncWakeupPromise = $promise instanceof \Generator ? new Coroutine($promise) : $promise;
|
||||
$this->asyncWakeupPromise->onResolve(
|
||||
function (?\Throwable $error, $result): void {
|
||||
$this->asyncWakeupPromise = null;
|
||||
}
|
||||
);
|
||||
}
|
||||
/**
|
||||
* Blockingly wakeup.
|
||||
*
|
||||
* @return mixed|null Resolves with the result of the wakeup function or null
|
||||
*/
|
||||
public function wakeup()
|
||||
{
|
||||
if ($this->asyncWakeupPromise) {
|
||||
return wait($this->asyncWakeupPromise);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
/**
|
||||
* Asynchronously wakeup.
|
||||
*
|
||||
* @return Promise<mixed|null> Resolves with the result of the wakeup function or null
|
||||
*/
|
||||
public function wakeupAsynchronously(): Promise
|
||||
{
|
||||
if ($this->asyncWakeupPromise) {
|
||||
return $this->asyncWakeupPromise;
|
||||
}
|
||||
return new Success();
|
||||
}
|
||||
/**
|
||||
* Check if we've already woken up.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function wokenUp(): bool
|
||||
{
|
||||
return !$this->asyncWakeupPromise;
|
||||
}
|
||||
/**
|
||||
* Mark instance as (de)woken up forcefully.
|
||||
*
|
||||
* @param boolean $woke Whether to mark the instance as woken up or not
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function forceWakeup(bool $woke): void
|
||||
{
|
||||
$this->asyncWakeupPromise = $woke ? null : new Success(null);
|
||||
}
|
||||
}
|
36
lib/BlockingConstruct.php
Normal file
36
lib/BlockingConstruct.php
Normal file
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Blocking constructor trait.
|
||||
*
|
||||
* @author Daniil Gentili <daniil@daniil.it>
|
||||
* @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
|
||||
* @license https://opensource.org/licenses/MIT MIT
|
||||
*/
|
||||
|
||||
namespace danog;
|
||||
|
||||
/**
|
||||
* Blocking constructor trait.
|
||||
*
|
||||
* Manages blocking construction of async classes
|
||||
*
|
||||
* @author Daniil Gentili <daniil@daniil.it>
|
||||
*/
|
||||
trait BlockingConstruct
|
||||
{
|
||||
use AsyncConstruct;
|
||||
|
||||
/**
|
||||
* Constructor function.
|
||||
*
|
||||
* @param mixed ...$params Parameters
|
||||
*/
|
||||
public function __construct(...$params)
|
||||
{
|
||||
if (\method_exists($this, '__construct_async')) {
|
||||
$this->setInitPromise($this->__construct_async(...$params));
|
||||
}
|
||||
$this->init();
|
||||
}
|
||||
}
|
34
lib/BlockingWakeup.php
Normal file
34
lib/BlockingWakeup.php
Normal file
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Blocking wakeup trait.
|
||||
*
|
||||
* @author Daniil Gentili <daniil@daniil.it>
|
||||
* @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
|
||||
* @license https://opensource.org/licenses/MIT MIT
|
||||
*/
|
||||
|
||||
namespace danog;
|
||||
|
||||
/**
|
||||
* Blocking wakeup trait.
|
||||
*
|
||||
* Manages blocking wakeup of async classes
|
||||
*
|
||||
* @author Daniil Gentili <daniil@daniil.it>
|
||||
*/
|
||||
trait BlockingWakeup
|
||||
{
|
||||
use AsyncWakeup;
|
||||
|
||||
/**
|
||||
* Wakeup function.
|
||||
*/
|
||||
public function __wakeup(): void
|
||||
{
|
||||
if (\method_exists($this, '__wakeup_async')) {
|
||||
$this->setWakeupPromise($this->__wakeup_async());
|
||||
}
|
||||
$this->wakeup();
|
||||
}
|
||||
}
|
28
phpunit.xml.dist
Normal file
28
phpunit.xml.dist
Normal file
@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<phpunit
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/4.1/phpunit.xsd"
|
||||
backupGlobals="false"
|
||||
backupStaticAttributes="false"
|
||||
bootstrap="vendor/autoload.php"
|
||||
colors="true"
|
||||
convertErrorsToExceptions="true"
|
||||
convertNoticesToExceptions="true"
|
||||
convertWarningsToExceptions="true"
|
||||
processIsolation="false"
|
||||
stopOnFailure="false"
|
||||
>
|
||||
<testsuites>
|
||||
<testsuite name="Amp Concurrent">
|
||||
<directory>test</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
<filter>
|
||||
<whitelist>
|
||||
<directory suffix=".php">lib</directory>
|
||||
</whitelist>
|
||||
</filter>
|
||||
<logging>
|
||||
<log type="coverage-html" target="build/coverage"/>
|
||||
</logging>
|
||||
</phpunit>
|
15
psalm.xml
Normal file
15
psalm.xml
Normal file
@ -0,0 +1,15 @@
|
||||
<?xml version="1.0"?>
|
||||
<psalm
|
||||
errorLevel="1"
|
||||
resolveFromConfigFile="true"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="https://getpsalm.org/schema/config"
|
||||
xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd"
|
||||
>
|
||||
<projectFiles>
|
||||
<directory name="lib" />
|
||||
<ignoreFiles>
|
||||
<directory name="vendor" />
|
||||
</ignoreFiles>
|
||||
</projectFiles>
|
||||
</psalm>
|
89
test/ConstructTest.php
Normal file
89
test/ConstructTest.php
Normal file
@ -0,0 +1,89 @@
|
||||
<?php
|
||||
|
||||
namespace danog\Test;
|
||||
|
||||
use Amp\PHPUnit\AsyncTestCase;
|
||||
use danog\AsyncConstruct;
|
||||
use danog\BlockingConstruct;
|
||||
use danog\Test\Fixtures\AsyncConstructTest;
|
||||
use danog\Test\Fixtures\BlockingConstructTest;
|
||||
|
||||
use function Amp\delay;
|
||||
|
||||
class ConstructTest extends AsyncTestCase
|
||||
{
|
||||
public function testAsyncInitBackground(): \Generator
|
||||
{
|
||||
$test = new AsyncConstructTest(100);
|
||||
$this->assertFalse($test->inited());
|
||||
$this->assertFalse($test->inited);
|
||||
yield delay(50);
|
||||
$this->assertFalse($test->inited());
|
||||
$this->assertFalse($test->inited);
|
||||
yield delay(51);
|
||||
$this->assertTrue($test->inited());
|
||||
$this->assertTrue($test->inited);
|
||||
}
|
||||
|
||||
public function testAsyncInit(): \Generator
|
||||
{
|
||||
$test = new AsyncConstructTest(100);
|
||||
$this->assertTrue(yield $test->initAsynchronously());
|
||||
$this->assertTrue($test->inited());
|
||||
$this->assertTrue($test->inited);
|
||||
$this->assertNull(yield $test->initAsynchronously());
|
||||
$this->assertTrue($test->inited());
|
||||
$this->assertTrue($test->inited);
|
||||
}
|
||||
|
||||
public function testAsyncInitBlocking()
|
||||
{
|
||||
$test = new AsyncConstructTest(100);
|
||||
$this->assertTrue($test->init());
|
||||
$this->assertTrue($test->inited());
|
||||
$this->assertTrue($test->inited);
|
||||
$this->assertNull($test->init());
|
||||
$this->assertTrue($test->inited());
|
||||
$this->assertTrue($test->inited);
|
||||
}
|
||||
|
||||
|
||||
public function testBlockingInit()
|
||||
{
|
||||
$test = new BlockingConstructTest(100);
|
||||
$this->assertTrue($test->inited());
|
||||
$this->assertTrue($test->inited);
|
||||
$this->assertNull($test->init());
|
||||
}
|
||||
|
||||
public function testNoInit()
|
||||
{
|
||||
$test = new class(100) {
|
||||
use AsyncConstruct;
|
||||
};
|
||||
$this->assertTrue($test->inited());
|
||||
$test = new class(100) {
|
||||
use BlockingConstruct;
|
||||
};
|
||||
$this->assertTrue($test->inited());
|
||||
}
|
||||
|
||||
public function testForceInit()
|
||||
{
|
||||
$test = new AsyncConstructTest(100);
|
||||
$test->forceInit(true);
|
||||
$this->assertTrue($test->inited());
|
||||
$this->assertNull($test->init());
|
||||
$test->forceInit(false);
|
||||
$this->assertFalse($test->inited());
|
||||
$this->assertNull($test->init());
|
||||
|
||||
$test = new BlockingConstructTest(100);
|
||||
$test->forceInit(true);
|
||||
$this->assertTrue($test->inited());
|
||||
$this->assertNull($test->init());
|
||||
$test->forceInit(false);
|
||||
$this->assertFalse($test->inited());
|
||||
$this->assertNull($test->init());
|
||||
}
|
||||
}
|
19
test/Fixtures/AsyncConstructTest.php
Normal file
19
test/Fixtures/AsyncConstructTest.php
Normal file
@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace danog\Test\Fixtures;
|
||||
|
||||
use danog\AsyncConstruct;
|
||||
|
||||
use function Amp\delay;
|
||||
|
||||
class AsyncConstructTest
|
||||
{
|
||||
use AsyncConstruct;
|
||||
public $inited = false;
|
||||
protected function __construct_async(int $delay): \Generator
|
||||
{
|
||||
yield delay($delay);
|
||||
$this->inited = true;
|
||||
return true;
|
||||
}
|
||||
}
|
24
test/Fixtures/AsyncWakeupTest.php
Normal file
24
test/Fixtures/AsyncWakeupTest.php
Normal file
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace danog\Test\Fixtures;
|
||||
|
||||
use danog\AsyncWakeup as AWakeup;
|
||||
|
||||
use function Amp\delay;
|
||||
|
||||
class AsyncWakeupTest
|
||||
{
|
||||
use AWakeup;
|
||||
public $woke = false;
|
||||
private $delay;
|
||||
public function __construct(int $delay)
|
||||
{
|
||||
$this->delay = $delay;
|
||||
}
|
||||
protected function __wakeup_async(): \Generator
|
||||
{
|
||||
yield delay($this->delay);
|
||||
$this->woke = true;
|
||||
return true;
|
||||
}
|
||||
}
|
19
test/Fixtures/BlockingConstructTest.php
Normal file
19
test/Fixtures/BlockingConstructTest.php
Normal file
@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace danog\Test\Fixtures;
|
||||
|
||||
use danog\BlockingConstruct;
|
||||
|
||||
use function Amp\delay;
|
||||
|
||||
class BlockingConstructTest
|
||||
{
|
||||
use BlockingConstruct;
|
||||
public $inited = false;
|
||||
protected function __construct_async(int $delay): \Generator
|
||||
{
|
||||
yield delay($delay);
|
||||
$this->inited = true;
|
||||
return true;
|
||||
}
|
||||
}
|
24
test/Fixtures/BlockingWakeupTest.php
Normal file
24
test/Fixtures/BlockingWakeupTest.php
Normal file
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace danog\Test\Fixtures;
|
||||
|
||||
use danog\BlockingWakeup;
|
||||
|
||||
use function Amp\delay;
|
||||
|
||||
class BlockingWakeupTest
|
||||
{
|
||||
use BlockingWakeup;
|
||||
public $woke = false;
|
||||
private $delay;
|
||||
public function __construct(int $delay)
|
||||
{
|
||||
$this->delay = $delay;
|
||||
}
|
||||
protected function __wakeup_async(): \Generator
|
||||
{
|
||||
yield delay($this->delay);
|
||||
$this->woke = true;
|
||||
return true;
|
||||
}
|
||||
}
|
101
test/WakeupTest.php
Normal file
101
test/WakeupTest.php
Normal file
@ -0,0 +1,101 @@
|
||||
<?php
|
||||
|
||||
namespace danog\Test;
|
||||
|
||||
use Amp\PHPUnit\AsyncTestCase;
|
||||
use danog\AsyncWakeup;
|
||||
use danog\BlockingWakeup;
|
||||
use danog\Test\Fixtures\AsyncWakeupTest as AsyncWakeupTest;
|
||||
use danog\Test\Fixtures\BlockingWakeupTest;
|
||||
|
||||
use function Amp\delay;
|
||||
|
||||
class WakeupTest extends AsyncTestCase
|
||||
{
|
||||
public function testAsyncWakeupBackground(): \Generator
|
||||
{
|
||||
$test = new AsyncWakeupTest(100);
|
||||
$this->assertFalse($test->woke);
|
||||
$test = \unserialize(\serialize($test));
|
||||
|
||||
$this->assertFalse($test->wokenUp());
|
||||
$this->assertFalse($test->woke);
|
||||
yield delay(50);
|
||||
$this->assertFalse($test->wokenUp());
|
||||
$this->assertFalse($test->woke);
|
||||
yield delay(51);
|
||||
$this->assertTrue($test->wokenUp());
|
||||
$this->assertTrue($test->woke);
|
||||
}
|
||||
|
||||
public function testAsyncWakeup(): \Generator
|
||||
{
|
||||
$test = new AsyncWakeupTest(100);
|
||||
$this->assertFalse($test->woke);
|
||||
$test = \unserialize(\serialize($test));
|
||||
|
||||
$this->assertTrue(yield $test->WakeupAsynchronously());
|
||||
$this->assertTrue($test->wokenUp());
|
||||
$this->assertTrue($test->woke);
|
||||
$this->assertNull(yield $test->WakeupAsynchronously());
|
||||
$this->assertTrue($test->wokenUp());
|
||||
$this->assertTrue($test->woke);
|
||||
}
|
||||
|
||||
public function testAsyncWakeupBlocking()
|
||||
{
|
||||
$test = new AsyncWakeupTest(100);
|
||||
$this->assertFalse($test->woke);
|
||||
$test = \unserialize(\serialize($test));
|
||||
|
||||
$this->assertTrue($test->Wakeup());
|
||||
$this->assertTrue($test->wokenUp());
|
||||
$this->assertTrue($test->woke);
|
||||
$this->assertNull($test->Wakeup());
|
||||
$this->assertTrue($test->wokenUp());
|
||||
$this->assertTrue($test->woke);
|
||||
}
|
||||
|
||||
|
||||
public function testBlockingWakeup()
|
||||
{
|
||||
$test = new BlockingWakeupTest(100);
|
||||
$this->assertFalse($test->woke);
|
||||
$test = \unserialize(\serialize($test));
|
||||
|
||||
$this->assertTrue($test->wokenUp());
|
||||
$this->assertTrue($test->woke);
|
||||
$this->assertNull($test->Wakeup());
|
||||
}
|
||||
|
||||
public function testNoWakeup()
|
||||
{
|
||||
$test = new class(100) {
|
||||
use AsyncWakeup;
|
||||
};
|
||||
$this->assertTrue($test->wokenUp());
|
||||
$test = new class(100) {
|
||||
use BlockingWakeup;
|
||||
};
|
||||
$this->assertTrue($test->wokenUp());
|
||||
}
|
||||
|
||||
public function testForceWakeup()
|
||||
{
|
||||
$test = new AsyncWakeupTest(100);
|
||||
$test->forceWakeup(true);
|
||||
$this->assertTrue($test->wokenUp());
|
||||
$this->assertNull($test->Wakeup());
|
||||
$test->forceWakeup(false);
|
||||
$this->assertFalse($test->wokenUp());
|
||||
$this->assertNull($test->Wakeup());
|
||||
|
||||
$test = new BlockingWakeupTest(100);
|
||||
$test->forceWakeup(true);
|
||||
$this->assertTrue($test->wokenUp());
|
||||
$this->assertNull($test->Wakeup());
|
||||
$test->forceWakeup(false);
|
||||
$this->assertFalse($test->wokenUp());
|
||||
$this->assertNull($test->Wakeup());
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user