pmmpthread support

This commit is contained in:
Dylan K. Taylor
2023-05-20 01:29:26 +01:00
parent 8454076235
commit e0630fbb25
24 changed files with 159 additions and 126 deletions

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")
);
}
}