pmmpthread support

This commit is contained in:
Dylan K. Taylor 2023-05-20 01:29:26 +01:00
parent 8454076235
commit e0630fbb25
No known key found for this signature in database
GPG Key ID: 8927471A91CAFD3D
24 changed files with 159 additions and 126 deletions

View File

@ -17,7 +17,7 @@ jobs:
steps:
- name: Build and prepare PHP cache
uses: pmmp/setup-php-action@c7fb29d83535320922068087c7285bdedbbfa3c2
uses: pmmp/setup-php-action@fa2accea978a84097cf40ecc7d46b2d71f258bd5
with:
php-version: ${{ matrix.php }}
install-path: "./bin"
@ -38,7 +38,7 @@ jobs:
- uses: actions/checkout@v3
- name: Setup PHP
uses: pmmp/setup-php-action@c7fb29d83535320922068087c7285bdedbbfa3c2
uses: pmmp/setup-php-action@fa2accea978a84097cf40ecc7d46b2d71f258bd5
with:
php-version: ${{ matrix.php }}
install-path: "./bin"
@ -77,7 +77,7 @@ jobs:
- uses: actions/checkout@v3
- name: Setup PHP
uses: pmmp/setup-php-action@c7fb29d83535320922068087c7285bdedbbfa3c2
uses: pmmp/setup-php-action@fa2accea978a84097cf40ecc7d46b2d71f258bd5
with:
php-version: ${{ matrix.php }}
install-path: "./bin"
@ -118,7 +118,7 @@ jobs:
submodules: true
- name: Setup PHP
uses: pmmp/setup-php-action@c7fb29d83535320922068087c7285bdedbbfa3c2
uses: pmmp/setup-php-action@fa2accea978a84097cf40ecc7d46b2d71f258bd5
with:
php-version: ${{ matrix.php }}
install-path: "./bin"
@ -157,7 +157,7 @@ jobs:
- uses: actions/checkout@v3
- name: Setup PHP
uses: pmmp/setup-php-action@c7fb29d83535320922068087c7285bdedbbfa3c2
uses: pmmp/setup-php-action@fa2accea978a84097cf40ecc7d46b2d71f258bd5
with:
php-version: ${{ matrix.php }}
install-path: "./bin"

View File

@ -22,7 +22,7 @@
"ext-openssl": "*",
"ext-pcre": "*",
"ext-phar": "*",
"ext-pthreads": "^5.1",
"ext-pmmpthread": "^6.0",
"ext-reflection": "*",
"ext-simplexml": "*",
"ext-sockets": "*",
@ -40,17 +40,17 @@
"pocketmine/bedrock-protocol": "~21.0.0+bedrock-1.19.80",
"pocketmine/binaryutils": "^0.2.1",
"pocketmine/callback-validator": "^1.0.2",
"pocketmine/classloader": "^0.3.0",
"pocketmine/classloader": "dev-stable",
"pocketmine/color": "^0.3.0",
"pocketmine/errorhandler": "^0.6.0",
"pocketmine/locale-data": "~2.19.0",
"pocketmine/log": "^0.4.0",
"pocketmine/log-pthreads": "^0.5.0",
"pocketmine/log-pthreads": "dev-stable",
"pocketmine/math": "^0.4.0",
"pocketmine/nbt": "^0.3.2",
"pocketmine/raklib": "^0.15.0",
"pocketmine/raklib-ipc": "^0.2.0",
"pocketmine/snooze": "^0.4.0",
"pocketmine/snooze": "dev-master",
"ramsey/uuid": "^4.1",
"symfony/filesystem": "^5.4"
},

79
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "8c09886bd34e74a61c3ea1ee2be3b2e9",
"content-hash": "507c2a45350440a7717ed089190fe4f0",
"packages": [
{
"name": "adhocore/json-comment",
@ -466,32 +466,33 @@
},
{
"name": "pocketmine/classloader",
"version": "0.3.0",
"version": "dev-stable",
"source": {
"type": "git",
"url": "https://github.com/pmmp/ClassLoader.git",
"reference": "407caf521186ec1f03024f39031cc681ad491026"
"reference": "e15c9b4d310581d2d2c9bf2794869cb940e011e1"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pmmp/ClassLoader/zipball/407caf521186ec1f03024f39031cc681ad491026",
"reference": "407caf521186ec1f03024f39031cc681ad491026",
"url": "https://api.github.com/repos/pmmp/ClassLoader/zipball/e15c9b4d310581d2d2c9bf2794869cb940e011e1",
"reference": "e15c9b4d310581d2d2c9bf2794869cb940e011e1",
"shasum": ""
},
"require": {
"ext-pthreads": "^5.0",
"ext-pmmpthread": "^6.0",
"ext-reflection": "*",
"php": "^8.0"
"php": "^8.1"
},
"conflict": {
"pocketmine/spl": "<0.4"
},
"require-dev": {
"phpstan/extension-installer": "^1.0",
"phpstan/phpstan": "1.9.4",
"phpstan/phpstan": "1.10.15",
"phpstan/phpstan-strict-rules": "^1.0",
"phpunit/phpunit": "^9.5"
},
"default-branch": true,
"type": "library",
"autoload": {
"classmap": [
@ -505,9 +506,9 @@
"description": "Ad-hoc autoloading components used by PocketMine-MP",
"support": {
"issues": "https://github.com/pmmp/ClassLoader/issues",
"source": "https://github.com/pmmp/ClassLoader/tree/0.3.0"
"source": "https://github.com/pmmp/ClassLoader/tree/stable"
},
"time": "2023-01-23T19:46:53+00:00"
"time": "2023-05-19T23:39:02+00:00"
},
{
"name": "pocketmine/color",
@ -652,21 +653,21 @@
},
{
"name": "pocketmine/log-pthreads",
"version": "0.5.0",
"version": "dev-stable",
"source": {
"type": "git",
"url": "https://github.com/pmmp/LogPthreads.git",
"reference": "0ecfea6dcfc9a9f5c86e126ac1661732de5c5666"
"reference": "bb3b5395042d12ec0d7ad5c855fd86eaf12869d3"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pmmp/LogPthreads/zipball/0ecfea6dcfc9a9f5c86e126ac1661732de5c5666",
"reference": "0ecfea6dcfc9a9f5c86e126ac1661732de5c5666",
"url": "https://api.github.com/repos/pmmp/LogPthreads/zipball/bb3b5395042d12ec0d7ad5c855fd86eaf12869d3",
"reference": "bb3b5395042d12ec0d7ad5c855fd86eaf12869d3",
"shasum": ""
},
"require": {
"ext-pthreads": "^5.0",
"php": "^8.0",
"ext-pmmpthread": "^6.0",
"php": "^8.1",
"pocketmine/log": "^0.4.0"
},
"conflict": {
@ -674,9 +675,10 @@
},
"require-dev": {
"phpstan/extension-installer": "^1.0",
"phpstan/phpstan": "1.8.11",
"phpstan/phpstan": "1.10.3",
"phpstan/phpstan-strict-rules": "^1.0"
},
"default-branch": true,
"type": "library",
"autoload": {
"classmap": [
@ -690,9 +692,9 @@
"description": "Logging components specialized for pthreads used by PocketMine-MP and related projects",
"support": {
"issues": "https://github.com/pmmp/LogPthreads/issues",
"source": "https://github.com/pmmp/LogPthreads/tree/0.5.0"
"source": "https://github.com/pmmp/LogPthreads/tree/stable"
},
"time": "2023-01-23T19:52:12+00:00"
"time": "2023-05-19T23:38:36+00:00"
},
{
"name": "pocketmine/math",
@ -863,27 +865,28 @@
},
{
"name": "pocketmine/snooze",
"version": "0.4.0",
"version": "dev-master",
"source": {
"type": "git",
"url": "https://github.com/pmmp/Snooze.git",
"reference": "6b1d6cc645d674590ff9be2438ac00032f9ee292"
"reference": "3207a201cbb10eebb4a96749678f7adef216bb71"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pmmp/Snooze/zipball/6b1d6cc645d674590ff9be2438ac00032f9ee292",
"reference": "6b1d6cc645d674590ff9be2438ac00032f9ee292",
"url": "https://api.github.com/repos/pmmp/Snooze/zipball/3207a201cbb10eebb4a96749678f7adef216bb71",
"reference": "3207a201cbb10eebb4a96749678f7adef216bb71",
"shasum": ""
},
"require": {
"ext-pthreads": "^5.0",
"php-64bit": "^8.0"
"ext-pmmpthread": "^6.0",
"php-64bit": "^8.1"
},
"require-dev": {
"phpstan/extension-installer": "^1.0",
"phpstan/phpstan": "1.9.14",
"phpstan/phpstan": "1.10.3",
"phpstan/phpstan-strict-rules": "^1.0"
},
"default-branch": true,
"type": "library",
"autoload": {
"psr-4": {
@ -897,9 +900,9 @@
"description": "Thread notification management library for code using the pthreads extension",
"support": {
"issues": "https://github.com/pmmp/Snooze/issues",
"source": "https://github.com/pmmp/Snooze/tree/0.4.0"
"source": "https://github.com/pmmp/Snooze/tree/master"
},
"time": "2023-01-23T19:43:19+00:00"
"time": "2023-05-19T23:38:19+00:00"
},
{
"name": "ramsey/collection",
@ -1527,16 +1530,16 @@
},
{
"name": "nikic/php-parser",
"version": "v4.15.4",
"version": "v4.15.5",
"source": {
"type": "git",
"url": "https://github.com/nikic/PHP-Parser.git",
"reference": "6bb5176bc4af8bcb7d926f88718db9b96a2d4290"
"reference": "11e2663a5bc9db5d714eedb4277ee300403b4a9e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/6bb5176bc4af8bcb7d926f88718db9b96a2d4290",
"reference": "6bb5176bc4af8bcb7d926f88718db9b96a2d4290",
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/11e2663a5bc9db5d714eedb4277ee300403b4a9e",
"reference": "11e2663a5bc9db5d714eedb4277ee300403b4a9e",
"shasum": ""
},
"require": {
@ -1577,9 +1580,9 @@
],
"support": {
"issues": "https://github.com/nikic/PHP-Parser/issues",
"source": "https://github.com/nikic/PHP-Parser/tree/v4.15.4"
"source": "https://github.com/nikic/PHP-Parser/tree/v4.15.5"
},
"time": "2023-03-05T19:49:14+00:00"
"time": "2023-05-19T20:20:00+00:00"
},
{
"name": "phar-io/manifest",
@ -3293,7 +3296,11 @@
],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": [],
"stability-flags": {
"pocketmine/classloader": 20,
"pocketmine/log-pthreads": 20,
"pocketmine/snooze": 20
},
"prefer-stable": false,
"prefer-lowest": false,
"platform": {
@ -3314,7 +3321,7 @@
"ext-openssl": "*",
"ext-pcre": "*",
"ext-phar": "*",
"ext-pthreads": "^5.1",
"ext-pmmpthread": "^6.0",
"ext-reflection": "*",
"ext-simplexml": "*",
"ext-sockets": "*",

View File

@ -44,7 +44,7 @@ parameters:
- tests/phpstan/stubs/JsonMapper.stub
- tests/phpstan/stubs/leveldb.stub
- tests/phpstan/stubs/phpasn1.stub
- tests/phpstan/stubs/pthreads.stub
- tests/phpstan/stubs/pmmpthread.stub
reportUnmatchedIgnoredErrors: false #no other way to silence platform-specific non-warnings
staticReflectionClassNamePatterns:
- "#^COM$#"

View File

@ -338,7 +338,7 @@ JIT_WARNING
$logger->info("Stopping other threads");
$killer = new ServerKiller(8);
$killer->start(PTHREADS_INHERIT_NONE);
$killer->start();
usleep(10000); //Fixes ServerKiller not being able to start on single-core machines
if(ThreadManager::getInstance()->stopAll() > 0){

View File

@ -417,7 +417,7 @@ class Server{
return $this->autoloader;
}
public function getLogger() : \AttachableThreadedLogger{
public function getLogger() : \AttachableThreadSafeLogger{
return $this->logger;
}
@ -760,7 +760,7 @@ class Server{
public function __construct(
private \DynamicClassLoader $autoloader,
private \AttachableThreadedLogger $logger,
private \AttachableThreadSafeLogger $logger,
string $dataPath,
string $pluginPath
){

View File

@ -23,6 +23,8 @@ declare(strict_types=1);
namespace pocketmine\console;
use pmmp\thread\Thread as NativeThread;
use pmmp\thread\ThreadSafeArray;
use pocketmine\utils\Process;
use function cli_set_process_title;
use function count;
@ -30,7 +32,6 @@ use function dirname;
use function feof;
use function fwrite;
use function stream_socket_client;
use const PTHREADS_INHERIT_NONE;
require dirname(__DIR__, 2) . '/vendor/autoload.php';
@ -46,14 +47,14 @@ if($socket === false){
throw new \RuntimeException("Failed to connect to server process ($errCode): $errMessage");
}
/** @phpstan-var \ThreadedArray<int, string> $channel */
$channel = new \ThreadedArray();
$thread = new class($channel) extends \Thread{
/** @phpstan-var ThreadSafeArray<int, string> $channel */
$channel = new ThreadSafeArray();
$thread = new class($channel) extends NativeThread{
/**
* @phpstan-param \ThreadedArray<int, string> $channel
* @phpstan-param ThreadSafeArray<int, string> $channel
*/
public function __construct(
private \ThreadedArray $channel,
private ThreadSafeArray $channel,
){}
public function run() : void{
@ -73,7 +74,7 @@ $thread = new class($channel) extends \Thread{
}
};
$thread->start(PTHREADS_INHERIT_NONE);
$thread->start(NativeThread::INHERIT_NONE);
while(!feof($socket)){
$line = $channel->synchronized(function() use ($channel) : ?string{
if(count($channel) === 0){

View File

@ -23,13 +23,14 @@ declare(strict_types=1);
namespace pocketmine\network\mcpe\raklib;
use pmmp\thread\ThreadSafeArray;
use raklib\server\ipc\InterThreadChannelReader;
final class PthreadsChannelReader implements InterThreadChannelReader{
/**
* @phpstan-param \ThreadedArray<int, string> $buffer
* @phpstan-param ThreadSafeArray<int, string> $buffer
*/
public function __construct(private \ThreadedArray $buffer){}
public function __construct(private ThreadSafeArray $buffer){}
public function read() : ?string{
return $this->buffer->shift();

View File

@ -23,13 +23,14 @@ declare(strict_types=1);
namespace pocketmine\network\mcpe\raklib;
use pmmp\thread\ThreadSafeArray;
use raklib\server\ipc\InterThreadChannelWriter;
final class PthreadsChannelWriter implements InterThreadChannelWriter{
/**
* @phpstan-param \ThreadedArray<int, string> $buffer
* @phpstan-param ThreadSafeArray<int, string> $buffer
*/
public function __construct(private \ThreadedArray $buffer){}
public function __construct(private ThreadSafeArray $buffer){}
public function write(string $str) : void{
$this->buffer[] = $str;

View File

@ -23,6 +23,7 @@ declare(strict_types=1);
namespace pocketmine\network\mcpe\raklib;
use pmmp\thread\ThreadSafeArray;
use pocketmine\lang\KnownTranslationFactory;
use pocketmine\network\AdvancedNetworkInterface;
use pocketmine\network\mcpe\compression\ZlibCompressor;
@ -105,10 +106,10 @@ class RakLibInterface implements ServerEventListener, AdvancedNetworkInterface{
$this->sleeper = new SleeperNotifier();
/** @phpstan-var \ThreadedArray<int, string> $mainToThreadBuffer */
$mainToThreadBuffer = new \ThreadedArray();
/** @phpstan-var \ThreadedArray<int, string> $threadToMainBuffer */
$threadToMainBuffer = new \ThreadedArray();
/** @phpstan-var ThreadSafeArray<int, string> $mainToThreadBuffer */
$mainToThreadBuffer = new ThreadSafeArray();
/** @phpstan-var ThreadSafeArray<int, string> $threadToMainBuffer */
$threadToMainBuffer = new ThreadSafeArray();
$this->rakLib = new RakLibServer(
$this->server->getLogger(),

View File

@ -23,6 +23,8 @@ declare(strict_types=1);
namespace pocketmine\network\mcpe\raklib;
use pmmp\thread\Thread as NativeThread;
use pmmp\thread\ThreadSafeArray;
use pocketmine\snooze\SleeperNotifier;
use pocketmine\thread\NonThreadSafeValue;
use pocketmine\thread\Thread;
@ -38,7 +40,6 @@ use function error_get_last;
use function gc_enable;
use function ini_set;
use function register_shutdown_function;
use const PTHREADS_INHERIT_NONE;
class RakLibServer extends Thread{
protected bool $cleanShutdown = false;
@ -50,13 +51,13 @@ class RakLibServer extends Thread{
protected NonThreadSafeValue $address;
/**
* @phpstan-param \ThreadedArray<int, string> $mainToThreadBuffer
* @phpstan-param \ThreadedArray<int, string> $threadToMainBuffer
* @phpstan-param ThreadSafeArray<int, string> $mainToThreadBuffer
* @phpstan-param ThreadSafeArray<int, string> $threadToMainBuffer
*/
public function __construct(
protected \ThreadedLogger $logger,
protected \ThreadedArray $mainToThreadBuffer,
protected \ThreadedArray $threadToMainBuffer,
protected \ThreadSafeLogger $logger,
protected ThreadSafeArray $mainToThreadBuffer,
protected ThreadSafeArray $threadToMainBuffer,
InternetAddress $address,
protected int $serverId,
protected int $maxMtuSize,
@ -88,13 +89,13 @@ class RakLibServer extends Thread{
}
private function setCrashInfo(RakLibThreadCrashInfo $info) : void{
$this->synchronized(function(RakLibThreadCrashInfo $info) : void{
$this->synchronized(function() use ($info) : void{
$this->crashInfo = new NonThreadSafeValue($info);
$this->notify();
}, $info);
});
}
public function startAndWait(int $options = PTHREADS_INHERIT_NONE) : void{
public function startAndWait(int $options = NativeThread::INHERIT_NONE) : void{
$this->start($options);
$this->synchronized(function() : void{
while(!$this->ready && $this->crashInfo === null){

View File

@ -23,15 +23,16 @@ declare(strict_types=1);
namespace pocketmine\network\mcpe\raklib;
use pmmp\thread\ThreadSafeArray;
use pocketmine\snooze\SleeperNotifier;
use raklib\server\ipc\InterThreadChannelWriter;
final class SnoozeAwarePthreadsChannelWriter implements InterThreadChannelWriter{
/**
* @phpstan-param \ThreadedArray<int, string> $buffer
* @phpstan-param ThreadSafeArray<int, string> $buffer
*/
public function __construct(
private \ThreadedArray $buffer,
private ThreadSafeArray $buffer,
private SleeperNotifier $notifier
){}

View File

@ -23,6 +23,8 @@ declare(strict_types=1);
namespace pocketmine\scheduler;
use pmmp\thread\Thread as NativeThread;
use pmmp\thread\ThreadSafeArray;
use pocketmine\snooze\SleeperHandler;
use pocketmine\snooze\SleeperNotifier;
use pocketmine\utils\Utils;
@ -33,14 +35,13 @@ use function count;
use function spl_object_id;
use function time;
use const PHP_INT_MAX;
use const PTHREADS_INHERIT_INI;
/**
* Manages general-purpose worker threads used for processing asynchronous tasks, and the tasks submitted to those
* workers.
*/
class AsyncPool{
private const WORKER_START_OPTIONS = PTHREADS_INHERIT_INI;
private const WORKER_START_OPTIONS = NativeThread::INHERIT_INI | NativeThread::INHERIT_COMMENTS;
/**
* @var \SplQueue[]|AsyncTask[][]
@ -69,7 +70,7 @@ class AsyncPool{
protected int $size,
private int $workerMemoryLimit,
private \ClassLoader $classLoader,
private \ThreadedLogger $logger,
private \ThreadSafeLogger $logger,
private SleeperHandler $eventLoop
){}
@ -158,7 +159,7 @@ class AsyncPool{
throw new \InvalidArgumentException("Cannot submit the same AsyncTask instance more than once");
}
$task->progressUpdates = new \ThreadedArray();
$task->progressUpdates = new ThreadSafeArray();
$task->setSubmitted();
$this->getWorker($worker)->stack($task);

View File

@ -23,7 +23,11 @@ declare(strict_types=1);
namespace pocketmine\scheduler;
use pmmp\thread\Runnable;
use pmmp\thread\Thread as NativeThread;
use pmmp\thread\ThreadSafeArray;
use pocketmine\thread\NonThreadSafeValue;
use function assert;
use function igbinary_serialize;
use function igbinary_unserialize;
use function is_null;
@ -54,7 +58,7 @@ use function spl_object_id;
* If you want to store non-thread-safe objects to access when the task completes, store them using
* {@link AsyncTask::storeLocal}.
*/
abstract class AsyncTask extends \ThreadedRunnable{
abstract class AsyncTask extends Runnable{
/**
* @var \ArrayObject|mixed[]|null object hash => mixed data
* @phpstan-var \ArrayObject<int, array<string, mixed>>|null
@ -63,11 +67,8 @@ abstract class AsyncTask extends \ThreadedRunnable{
*/
private static ?\ArrayObject $threadLocalStorage = null;
/** @var AsyncWorker|null $worker */
public $worker = null;
/** @phpstan-var \ThreadedArray<int, string> */
public \ThreadedArray $progressUpdates;
/** @phpstan-var ThreadSafeArray<int, string> */
public ThreadSafeArray $progressUpdates;
/** @phpstan-var NonThreadSafeValue<mixed>|string|int|bool|float|null */
private NonThreadSafeValue|string|int|bool|null|float $result = null;
@ -85,12 +86,15 @@ abstract class AsyncTask extends \ThreadedRunnable{
$this->onRun();
}catch(\Throwable $e){
$this->crashed = true;
$this->worker->handleException($e);
\GlobalLogger::get()->logException($e);
}
}
$this->finished = true;
$this->worker->getNotifier()->wakeupSleeper();
$worker = NativeThread::getCurrentThread();
assert($worker instanceof AsyncWorker);
$worker->getNotifier()->wakeupSleeper();
}
public function isCrashed() : bool{

View File

@ -23,6 +23,7 @@ declare(strict_types=1);
namespace pocketmine\scheduler;
use pmmp\thread\Thread as NativeThread;
use pocketmine\snooze\SleeperNotifier;
use pocketmine\thread\Worker;
use function gc_enable;
@ -33,7 +34,7 @@ class AsyncWorker extends Worker{
private static array $store = [];
public function __construct(
private \ThreadedLogger $logger,
private \ThreadSafeLogger $logger,
private int $id,
private int $memoryLimit,
private SleeperNotifier $notifier
@ -57,7 +58,7 @@ class AsyncWorker extends Worker{
}
}
public function getLogger() : \ThreadedLogger{
public function getLogger() : \ThreadSafeLogger{
return $this->logger;
}
@ -78,7 +79,7 @@ class AsyncWorker extends Worker{
* want to use on this worker thread from multiple AsyncTasks.
*/
public function saveToThreadStore(string $identifier, mixed $value) : void{
if(\Thread::getCurrentThread() !== $this){
if(NativeThread::getCurrentThread() !== $this){
throw new \LogicException("Thread-local data can only be stored in the thread context");
}
self::$store[$identifier] = $value;
@ -93,7 +94,7 @@ class AsyncWorker extends Worker{
* Objects stored in this storage may ONLY be retrieved while the task is running.
*/
public function getFromThreadStore(string $identifier) : mixed{
if(\Thread::getCurrentThread() !== $this){
if(NativeThread::getCurrentThread() !== $this){
throw new \LogicException("Thread-local data can only be fetched in the thread context");
}
return self::$store[$identifier] ?? null;
@ -103,7 +104,7 @@ class AsyncWorker extends Worker{
* Removes previously-stored mixed data from the worker's thread-local object store.
*/
public function removeFromThreadStore(string $identifier) : void{
if(\Thread::getCurrentThread() !== $this){
if(NativeThread::getCurrentThread() !== $this){
throw new \LogicException("Thread-local data can only be removed in the thread context");
}
unset(self::$store[$identifier]);

View File

@ -23,8 +23,10 @@ declare(strict_types=1);
namespace pocketmine\scheduler;
use pmmp\thread\Thread as NativeThread;
use pocketmine\MemoryManager;
use Symfony\Component\Filesystem\Path;
use function assert;
/**
* Task used to dump memory from AsyncWorkers
@ -37,12 +39,14 @@ class DumpWorkerMemoryTask extends AsyncTask{
){}
public function onRun() : void{
$worker = NativeThread::getCurrentThread();
assert($worker instanceof AsyncWorker);
MemoryManager::dumpMemory(
$this->worker,
Path::join($this->outputFolder, "AsyncWorker#" . $this->worker->getAsyncWorkerId()),
$worker,
Path::join($this->outputFolder, "AsyncWorker#" . $worker->getAsyncWorkerId()),
$this->maxNesting,
$this->maxStringSize,
new \PrefixedLogger($this->worker->getLogger(), "Memory Dump")
new \PrefixedLogger($worker->getLogger(), "Memory Dump")
);
}
}

View File

@ -23,16 +23,17 @@ declare(strict_types=1);
namespace pocketmine\thread;
use pmmp\thread\ThreadSafeArray;
use pocketmine\errorhandler\ErrorToExceptionHandler;
use pocketmine\Server;
use function error_reporting;
trait CommonThreadPartsTrait{
/**
* @var \ThreadedArray|\ClassLoader[]|null
* @phpstan-var \ThreadedArray<int, \ClassLoader>|null
* @var ThreadSafeArray|\ClassLoader[]|null
* @phpstan-var ThreadSafeArray<int, \ClassLoader>|null
*/
private ?\ThreadedArray $classLoaders = null;
private ?ThreadSafeArray $classLoaders = null;
protected ?string $composerAutoloaderPath = null;
protected bool $isKilled = false;
@ -55,14 +56,15 @@ trait CommonThreadPartsTrait{
}
if($this->classLoaders === null){
$this->classLoaders = new \ThreadedArray();
$loaders = $this->classLoaders = new ThreadSafeArray();
}else{
$loaders = $this->classLoaders;
foreach($this->classLoaders as $k => $autoloader){
unset($this->classLoaders[$k]);
}
}
foreach($autoloaders as $autoloader){
$this->classLoaders[] = $autoloader;
$loaders[] = $autoloader;
}
}

View File

@ -23,6 +23,7 @@ declare(strict_types=1);
namespace pocketmine\thread;
use pmmp\thread\ThreadSafe;
use function get_debug_type;
use function igbinary_serialize;
use function igbinary_unserialize;
@ -34,7 +35,7 @@ use function igbinary_unserialize;
*
* @phpstan-template TValue
*/
final class NonThreadSafeValue extends \ThreadedBase{
final class NonThreadSafeValue extends ThreadSafe{
private string $variable;
/**

View File

@ -23,8 +23,8 @@ declare(strict_types=1);
namespace pocketmine\thread;
use pmmp\thread\Thread as NativeThread;
use pocketmine\scheduler\AsyncTask;
use const PTHREADS_INHERIT_NONE;
/**
* Specialized Thread class aimed at PocketMine-MP-related usages. It handles setting up autoloading and error handling.
@ -35,10 +35,10 @@ use const PTHREADS_INHERIT_NONE;
* CPU.
* @see AsyncTask
*/
abstract class Thread extends \Thread{
abstract class Thread extends NativeThread{
use CommonThreadPartsTrait;
public function start(int $options = PTHREADS_INHERIT_NONE) : bool{
public function start(int $options = NativeThread::INHERIT_NONE) : bool{
//this is intentionally not traitified
ThreadManager::getInstance()->add($this);

View File

@ -23,9 +23,11 @@ declare(strict_types=1);
namespace pocketmine\thread;
use pmmp\thread\ThreadSafe;
use pmmp\thread\ThreadSafeArray;
use function spl_object_id;
class ThreadManager extends \ThreadedBase{
class ThreadManager extends ThreadSafe{
private static ?self $instance = null;
@ -40,11 +42,11 @@ class ThreadManager extends \ThreadedBase{
return self::$instance;
}
/** @phpstan-var \ThreadedArray<int, Thread|Worker> */
private \ThreadedArray $threads;
/** @phpstan-var ThreadSafeArray<int, Thread|Worker> */
private ThreadSafeArray $threads;
private function __construct(){
$this->threads = new \ThreadedArray();
$this->threads = new ThreadSafeArray();
}
public function add(Worker|Thread $thread) : void{

View File

@ -23,8 +23,9 @@ declare(strict_types=1);
namespace pocketmine\thread;
use pmmp\thread\Thread as NativeThread;
use pmmp\thread\Worker as NativeWorker;
use pocketmine\scheduler\AsyncTask;
use const PTHREADS_INHERIT_NONE;
/**
* Specialized Worker class for PocketMine-MP-related use cases. It handles setting up autoloading and error handling.
@ -36,10 +37,10 @@ use const PTHREADS_INHERIT_NONE;
* If you want to run tasks on other CPU cores, check out AsyncTask first.
* @see AsyncTask
*/
abstract class Worker extends \Worker{
abstract class Worker extends NativeWorker{
use CommonThreadPartsTrait;
public function start(int $options = PTHREADS_INHERIT_NONE) : bool{
public function start(int $options = NativeThread::INHERIT_NONE) : bool{
//this is intentionally not traitified
ThreadManager::getInstance()->add($this);

View File

@ -24,14 +24,14 @@ declare(strict_types=1);
namespace pocketmine\utils;
use LogLevel;
use pmmp\thread\Thread as NativeThread;
use pocketmine\thread\Thread;
use pocketmine\thread\Worker;
use function implode;
use function sprintf;
use const PHP_EOL;
use const PTHREADS_INHERIT_NONE;
class MainLogger extends \AttachableThreadedLogger implements \BufferedLogger{
class MainLogger extends \AttachableThreadSafeLogger implements \BufferedLogger{
protected bool $logDebug;
private string $format = TextFormat::AQUA . "[%s] " . TextFormat::RESET . "%s[%s/%s]: %s" . TextFormat::RESET;
@ -52,7 +52,7 @@ class MainLogger extends \AttachableThreadedLogger implements \BufferedLogger{
$this->timezone = $timezone->getName();
$this->logWriterThread = new MainLoggerThread($logFile);
$this->logWriterThread->start(PTHREADS_INHERIT_NONE);
$this->logWriterThread->start(NativeThread::INHERIT_NONE);
}
/**
@ -165,7 +165,7 @@ class MainLogger extends \AttachableThreadedLogger implements \BufferedLogger{
}
public function shutdownLogWriterThread() : void{
if(\Thread::getCurrentThreadId() === $this->logWriterThread->getCreatorId()){
if(NativeThread::getCurrentThreadId() === $this->logWriterThread->getCreatorId()){
$this->logWriterThread->shutdown();
}else{
throw new \LogicException("Only the creator thread can shutdown the logger thread");
@ -175,7 +175,7 @@ class MainLogger extends \AttachableThreadedLogger implements \BufferedLogger{
protected function send(string $message, string $level, string $prefix, string $color) : void{
$time = new \DateTime('now', new \DateTimeZone($this->timezone));
$thread = \Thread::getCurrentThread();
$thread = NativeThread::getCurrentThread();
if($thread === null){
$threadName = $this->mainThreadName . " thread";
}elseif($thread instanceof Thread || $thread instanceof Worker){
@ -195,7 +195,7 @@ class MainLogger extends \AttachableThreadedLogger implements \BufferedLogger{
$this->logWriterThread->write($time->format("Y-m-d") . " " . TextFormat::clean($message) . PHP_EOL);
/**
* @var \ThreadedLoggerAttachment $attachment
* @var \ThreadSafeLoggerAttachment $attachment
*/
foreach($this->attachments as $attachment){
$attachment->log($level, $message);
@ -208,7 +208,7 @@ class MainLogger extends \AttachableThreadedLogger implements \BufferedLogger{
}
public function __destruct(){
if(!$this->logWriterThread->isJoined() && \Thread::getCurrentThreadId() === $this->logWriterThread->getCreatorId()){
if(!$this->logWriterThread->isJoined() && NativeThread::getCurrentThreadId() === $this->logWriterThread->getCreatorId()){
$this->shutdownLogWriterThread();
}
}

View File

@ -23,22 +23,24 @@ declare(strict_types=1);
namespace pocketmine\utils;
use pmmp\thread\Thread;
use pmmp\thread\ThreadSafeArray;
use function fclose;
use function fopen;
use function fwrite;
use function is_resource;
use function touch;
final class MainLoggerThread extends \Thread{
/** @phpstan-var \ThreadedArray<int, string> */
private \ThreadedArray $buffer;
final class MainLoggerThread extends Thread{
/** @phpstan-var ThreadSafeArray<int, string> */
private ThreadSafeArray $buffer;
private bool $syncFlush = false;
private bool $shutdown = false;
public function __construct(
private string $logFile
){
$this->buffer = new \ThreadedArray();
$this->buffer = new ThreadSafeArray();
touch($this->logFile);
}

View File

@ -1,9 +1,11 @@
<?php
namespace pmmp\thread;
/**
* @implements \IteratorAggregate<array-key, mixed>
*/
abstract class ThreadedBase implements \IteratorAggregate{
abstract class ThreadSafe implements \IteratorAggregate{
/**
* @template TReturn
@ -17,9 +19,9 @@ abstract class ThreadedBase implements \IteratorAggregate{
/**
* @template TKey of array-key
* @template TValue
* @implements ArrayAccess<TKey, TValue>
* @implements \ArrayAccess<TKey, TValue>
*/
final class ThreadedArray extends ThreadedBase implements Countable, ArrayAccess{
final class ThreadSafeArray extends ThreadSafe implements \Countable, \ArrayAccess{
/**
* @return TValue|null
@ -30,4 +32,4 @@ final class ThreadedArray extends ThreadedBase implements Countable, ArrayAccess
* @return TValue|null
*/
public function shift() : mixed{}
}
}