mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-05-09 07:20:15 +00:00
this is now supported thanks to the object rescue feature implemented in pthreads 5.1, making returning of thread-safe values from async tasks possible. This needs to be explicitly supported, since otherwise it will attempt to serialize them, which isn't supported anymore.
92 lines
2.7 KiB
PHP
92 lines
2.7 KiB
PHP
<?php
|
|
|
|
/*
|
|
*
|
|
* ____ _ _ __ __ _ __ __ ____
|
|
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
|
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
|
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
|
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU Lesser General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* @author PocketMine Team
|
|
* @link http://www.pocketmine.net/
|
|
*
|
|
*
|
|
*/
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace pocketmine\scheduler;
|
|
|
|
use PHPUnit\Framework\TestCase;
|
|
use pmmp\thread\ThreadSafeArray;
|
|
use pocketmine\promise\PromiseResolver;
|
|
use pocketmine\snooze\SleeperHandler;
|
|
use pocketmine\utils\MainLogger;
|
|
use function define;
|
|
use function dirname;
|
|
use function microtime;
|
|
use function sys_get_temp_dir;
|
|
use function tempnam;
|
|
use function usleep;
|
|
|
|
class AsyncPoolTest extends TestCase{
|
|
|
|
/** @var AsyncPool */
|
|
private $pool;
|
|
/** @var MainLogger */
|
|
private $mainLogger;
|
|
|
|
public function setUp() : void{
|
|
@define('pocketmine\\COMPOSER_AUTOLOADER_PATH', dirname(__DIR__, 3) . '/vendor/autoload.php');
|
|
$this->mainLogger = new MainLogger(tempnam(sys_get_temp_dir(), "pmlog"), false, "Main", new \DateTimeZone('UTC'));
|
|
$this->pool = new AsyncPool(2, 1024, new \BaseClassLoader(), $this->mainLogger, new SleeperHandler());
|
|
}
|
|
|
|
public function tearDown() : void{
|
|
$this->pool->shutdown();
|
|
$this->mainLogger->shutdownLogWriterThread();
|
|
}
|
|
|
|
public function testTaskLeak() : void{
|
|
$start = microtime(true);
|
|
$this->pool->submitTask(new LeakTestAsyncTask());
|
|
while(!LeakTestAsyncTask::$destroyed && microtime(true) < $start + 30){
|
|
usleep(50 * 1000);
|
|
$this->pool->collectTasks();
|
|
}
|
|
self::assertTrue(LeakTestAsyncTask::$destroyed, "Task was not destroyed after 30 seconds");
|
|
}
|
|
|
|
public function testPublishProgressRace() : void{
|
|
$task = new PublishProgressRaceAsyncTask();
|
|
$this->pool->submitTask($task);
|
|
while($this->pool->collectTasks()){
|
|
usleep(50 * 1000);
|
|
}
|
|
self::assertTrue(PublishProgressRaceAsyncTask::$success, "Progress was not reported before task completion");
|
|
}
|
|
|
|
public function testThreadSafeSetResult() : void{
|
|
$resolver = new PromiseResolver();
|
|
$resolver->getPromise()->onCompletion(
|
|
function(ThreadSafeArray $result) : void{
|
|
self::assertCount(1, $result);
|
|
self::assertSame(["foo"], (array) $result);
|
|
},
|
|
function() : void{
|
|
self::fail("Promise failed");
|
|
}
|
|
);
|
|
$this->pool->submitTask(new ThreadSafeResultAsyncTask($resolver));
|
|
while($this->pool->collectTasks()){
|
|
usleep(50 * 1000);
|
|
}
|
|
}
|
|
}
|