mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-09-04 17:06:16 +00:00
Merge branch 'stable' into next-minor
This commit is contained in:
@ -67,7 +67,10 @@ class AsyncPool{
|
||||
/** @var int[] */
|
||||
private $workerLastUsed = [];
|
||||
|
||||
/** @var \Closure[] */
|
||||
/**
|
||||
* @var \Closure[]
|
||||
* @phpstan-var (\Closure(int $workerId) : void)[]
|
||||
*/
|
||||
private $workerStartHooks = [];
|
||||
|
||||
public function __construct(Server $server, int $size, int $workerMemoryLimit, \ClassLoader $classLoader, \ThreadedLogger $logger){
|
||||
@ -80,8 +83,6 @@ class AsyncPool{
|
||||
|
||||
/**
|
||||
* Returns the maximum size of the pool. Note that there may be less active workers than this number.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getSize() : int{
|
||||
return $this->size;
|
||||
@ -89,8 +90,6 @@ class AsyncPool{
|
||||
|
||||
/**
|
||||
* Increases the maximum size of the pool to the specified amount. This does not immediately start new workers.
|
||||
*
|
||||
* @param int $newSize
|
||||
*/
|
||||
public function increaseSize(int $newSize) : void{
|
||||
if($newSize > $this->size){
|
||||
@ -104,7 +103,7 @@ class AsyncPool{
|
||||
*
|
||||
* This function will call the hook for every already-running worker.
|
||||
*
|
||||
* @param \Closure $hook
|
||||
* @phpstan-param \Closure(int $workerId) : void $hook
|
||||
*/
|
||||
public function addWorkerStartHook(\Closure $hook) : void{
|
||||
Utils::validateCallableSignature(function(int $worker) : void{}, $hook);
|
||||
@ -117,7 +116,7 @@ class AsyncPool{
|
||||
/**
|
||||
* Removes a previously-registered callback listening for workers being started.
|
||||
*
|
||||
* @param \Closure $hook
|
||||
* @phpstan-param \Closure(int $workerId) : void $hook
|
||||
*/
|
||||
public function removeWorkerStartHook(\Closure $hook) : void{
|
||||
unset($this->workerStartHooks[spl_object_hash($hook)]);
|
||||
@ -135,10 +134,6 @@ class AsyncPool{
|
||||
/**
|
||||
* Fetches the worker with the specified ID, starting it if it does not exist, and firing any registered worker
|
||||
* start hooks.
|
||||
*
|
||||
* @param int $worker
|
||||
*
|
||||
* @return AsyncWorker
|
||||
*/
|
||||
private function getWorker(int $worker) : AsyncWorker{
|
||||
if(!isset($this->workers[$worker])){
|
||||
@ -157,9 +152,6 @@ class AsyncPool{
|
||||
|
||||
/**
|
||||
* Submits an AsyncTask to an arbitrary worker.
|
||||
*
|
||||
* @param AsyncTask $task
|
||||
* @param int $worker
|
||||
*/
|
||||
public function submitTaskToWorker(AsyncTask $task, int $worker) : void{
|
||||
if($worker < 0 or $worker >= $this->size){
|
||||
@ -186,8 +178,6 @@ class AsyncPool{
|
||||
* - if an idle worker is found, it will be selected
|
||||
* - else, if the worker pool is not full, a new worker will be selected
|
||||
* - else, the worker with the smallest backlog is chosen.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function selectWorker() : int{
|
||||
$worker = null;
|
||||
@ -218,10 +208,6 @@ class AsyncPool{
|
||||
/**
|
||||
* Submits an AsyncTask to the worker with the least load. If all workers are busy and the pool is not full, a new
|
||||
* worker may be started.
|
||||
*
|
||||
* @param AsyncTask $task
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function submitTask(AsyncTask $task) : int{
|
||||
if($task->getTaskId() !== null){
|
||||
@ -235,9 +221,6 @@ class AsyncPool{
|
||||
|
||||
/**
|
||||
* Removes a completed or crashed task from the pool.
|
||||
*
|
||||
* @param AsyncTask $task
|
||||
* @param bool $force
|
||||
*/
|
||||
private function removeTask(AsyncTask $task, bool $force = false) : void{
|
||||
if(isset($this->taskWorkers[$task->getTaskId()])){
|
||||
|
@ -53,20 +53,27 @@ abstract class AsyncTask extends Collectable{
|
||||
*/
|
||||
private static $threadLocalStorage;
|
||||
|
||||
/** @var AsyncWorker $worker */
|
||||
/** @var AsyncWorker|null $worker */
|
||||
public $worker = null;
|
||||
|
||||
/** @var \Threaded */
|
||||
public $progressUpdates;
|
||||
|
||||
/** @var scalar|null */
|
||||
private $result = null;
|
||||
/** @var bool */
|
||||
private $serialized = false;
|
||||
/** @var bool */
|
||||
private $cancelRun = false;
|
||||
/** @var int|null */
|
||||
private $taskId = null;
|
||||
|
||||
/** @var bool */
|
||||
private $crashed = false;
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function run(){
|
||||
$this->result = null;
|
||||
|
||||
@ -93,6 +100,9 @@ abstract class AsyncTask extends Collectable{
|
||||
return $this->serialized ? unserialize($this->result) : $this->result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function cancelRun(){
|
||||
$this->cancelRun = true;
|
||||
}
|
||||
@ -101,20 +111,22 @@ abstract class AsyncTask extends Collectable{
|
||||
return $this->cancelRun;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function hasResult() : bool{
|
||||
return $this->result !== null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $result
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setResult($result){
|
||||
$this->result = ($this->serialized = !is_scalar($result)) ? serialize($result) : $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function setTaskId(int $taskId){
|
||||
$this->taskId = $taskId;
|
||||
}
|
||||
@ -130,8 +142,6 @@ abstract class AsyncTask extends Collectable{
|
||||
* @deprecated
|
||||
* @see AsyncWorker::getFromThreadStore()
|
||||
*
|
||||
* @param string $identifier
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getFromThreadStore(string $identifier){
|
||||
@ -145,8 +155,9 @@ abstract class AsyncTask extends Collectable{
|
||||
* @deprecated
|
||||
* @see AsyncWorker::saveToThreadStore()
|
||||
*
|
||||
* @param string $identifier
|
||||
* @param mixed $value
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function saveToThreadStore(string $identifier, $value){
|
||||
if($this->worker === null or $this->isGarbage()){
|
||||
@ -158,8 +169,6 @@ abstract class AsyncTask extends Collectable{
|
||||
/**
|
||||
* @deprecated
|
||||
* @see AsyncWorker::removeFromThreadStore()
|
||||
*
|
||||
* @param string $identifier
|
||||
*/
|
||||
public function removeFromThreadStore(string $identifier) : void{
|
||||
if($this->worker === null or $this->isGarbage()){
|
||||
@ -179,8 +188,6 @@ abstract class AsyncTask extends Collectable{
|
||||
* Actions to execute when completed (on main thread)
|
||||
* Implement this if you want to handle the data in your AsyncTask after it has been processed
|
||||
*
|
||||
* @param Server $server
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function onCompletion(Server $server){
|
||||
@ -192,6 +199,8 @@ abstract class AsyncTask extends Collectable{
|
||||
* {@link AsyncTask::onProgressUpdate} from the main thread with the given progress parameter.
|
||||
*
|
||||
* @param mixed $progress A value that can be safely serialize()'ed.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function publishProgress($progress){
|
||||
$this->progressUpdates[] = serialize($progress);
|
||||
@ -200,7 +209,7 @@ abstract class AsyncTask extends Collectable{
|
||||
/**
|
||||
* @internal Only call from AsyncPool.php on the main thread
|
||||
*
|
||||
* @param Server $server
|
||||
* @return void
|
||||
*/
|
||||
public function checkProgressUpdates(Server $server){
|
||||
while($this->progressUpdates->count() !== 0){
|
||||
@ -214,9 +223,10 @@ abstract class AsyncTask extends Collectable{
|
||||
* All {@link AsyncTask::publishProgress} calls should result in {@link AsyncTask::onProgressUpdate} calls before
|
||||
* {@link AsyncTask::onCompletion} is called.
|
||||
*
|
||||
* @param Server $server
|
||||
* @param mixed $progress The parameter passed to {@link AsyncTask::publishProgress}. It is serialize()'ed
|
||||
* and then unserialize()'ed, as if it has been cloned.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function onProgressUpdate(Server $server, $progress){
|
||||
|
||||
@ -233,6 +243,7 @@ abstract class AsyncTask extends Collectable{
|
||||
*
|
||||
* @param mixed $complexData the data to store
|
||||
*
|
||||
* @return void
|
||||
* @throws \BadMethodCallException if called from any thread except the main thread
|
||||
*/
|
||||
protected function storeLocal($complexData){
|
||||
|
@ -35,7 +35,9 @@ class AsyncWorker extends Worker{
|
||||
/** @var mixed[] */
|
||||
private static $store = [];
|
||||
|
||||
/** @var \ThreadedLogger */
|
||||
private $logger;
|
||||
/** @var int */
|
||||
private $id;
|
||||
|
||||
/** @var int */
|
||||
@ -47,6 +49,9 @@ class AsyncWorker extends Worker{
|
||||
$this->memoryLimit = $memoryLimit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function run(){
|
||||
error_reporting(-1);
|
||||
|
||||
@ -74,6 +79,9 @@ class AsyncWorker extends Worker{
|
||||
return $this->logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function handleException(\Throwable $e){
|
||||
$this->logger->logException($e);
|
||||
}
|
||||
@ -90,7 +98,6 @@ class AsyncWorker extends Worker{
|
||||
* Saves mixed data into the worker's thread-local object store. This can be used to store objects which you
|
||||
* want to use on this worker thread from multiple AsyncTasks.
|
||||
*
|
||||
* @param string $identifier
|
||||
* @param mixed $value
|
||||
*/
|
||||
public function saveToThreadStore(string $identifier, $value) : void{
|
||||
@ -105,8 +112,6 @@ class AsyncWorker extends Worker{
|
||||
*
|
||||
* Objects stored in this storage may ONLY be retrieved while the task is running.
|
||||
*
|
||||
* @param string $identifier
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getFromThreadStore(string $identifier){
|
||||
@ -115,8 +120,6 @@ class AsyncWorker extends Worker{
|
||||
|
||||
/**
|
||||
* Removes previously-stored mixed data from the worker's thread-local object store.
|
||||
*
|
||||
* @param string $identifier
|
||||
*/
|
||||
public function removeFromThreadStore(string $identifier) : void{
|
||||
unset(self::$store[$identifier]);
|
||||
|
@ -34,6 +34,7 @@ use function unserialize;
|
||||
* The result of this AsyncTask is an array of arrays (returned from {@link Internet::simpleCurl}) or InternetException objects.
|
||||
*/
|
||||
class BulkCurlTask extends AsyncTask{
|
||||
/** @var string */
|
||||
private $operations;
|
||||
|
||||
/**
|
||||
@ -43,8 +44,9 @@ class BulkCurlTask extends AsyncTask{
|
||||
* "timeout", "extraHeaders" and "extraOpts". Documentation of these options are same as those in
|
||||
* {@link Utils::simpleCurl}.
|
||||
*
|
||||
* @param array $operations
|
||||
* @param mixed[][] $operations
|
||||
* @param mixed|null $complexData
|
||||
* @phpstan-param list<array{page: string, timeout?: float, extraHeaders?: list<string>, extraOpts?: array<int, mixed>}> $operations
|
||||
*/
|
||||
public function __construct(array $operations, $complexData = null){
|
||||
$this->storeLocal($complexData);
|
||||
@ -52,6 +54,7 @@ class BulkCurlTask extends AsyncTask{
|
||||
}
|
||||
|
||||
public function onRun(){
|
||||
/** @phpstan-var list<array{page: string, timeout?: float, extraHeaders?: list<string>, extraOpts?: array<int, mixed>}> $operations */
|
||||
$operations = unserialize($this->operations);
|
||||
$results = [];
|
||||
foreach($operations as $op){
|
||||
|
@ -38,11 +38,15 @@ use pocketmine\utils\Utils;
|
||||
*/
|
||||
class ClosureTask extends Task{
|
||||
|
||||
/** @var \Closure */
|
||||
/**
|
||||
* @var \Closure
|
||||
* @phpstan-var \Closure(int) : void
|
||||
*/
|
||||
private $closure;
|
||||
|
||||
/**
|
||||
* @param \Closure $closure Must accept only ONE parameter, $currentTick
|
||||
* @phpstan-param \Closure(int) : void $closure
|
||||
*/
|
||||
public function __construct(\Closure $closure){
|
||||
Utils::validateCallableSignature(function(int $currentTick){}, $closure);
|
||||
|
@ -37,11 +37,6 @@ class DumpWorkerMemoryTask extends AsyncTask{
|
||||
/** @var int */
|
||||
private $maxStringSize;
|
||||
|
||||
/**
|
||||
* @param string $outputFolder
|
||||
* @param int $maxNesting
|
||||
* @param int $maxStringSize
|
||||
*/
|
||||
public function __construct(string $outputFolder, int $maxNesting, int $maxStringSize){
|
||||
$this->outputFolder = $outputFolder;
|
||||
$this->maxNesting = $maxNesting;
|
||||
|
@ -35,9 +35,7 @@ class FileWriteTask extends AsyncTask{
|
||||
private $flags;
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
* @param mixed $contents
|
||||
* @param int $flags
|
||||
*/
|
||||
public function __construct(string $path, $contents, int $flags = 0){
|
||||
$this->path = $path;
|
||||
|
@ -45,13 +45,14 @@ class SendUsageTask extends AsyncTask{
|
||||
public const TYPE_STATUS = 2;
|
||||
public const TYPE_CLOSE = 3;
|
||||
|
||||
/** @var string */
|
||||
public $endpoint;
|
||||
/** @var string */
|
||||
public $data;
|
||||
|
||||
/**
|
||||
* @param Server $server
|
||||
* @param int $type
|
||||
* @param array $playerList
|
||||
* @param string[] $playerList
|
||||
* @phpstan-param array<string, string> $playerList
|
||||
*/
|
||||
public function __construct(Server $server, int $type, array $playerList = []){
|
||||
$endpoint = "http://" . $server->getProperty("anonymous-statistics.host", "stats.pocketmine.net") . "/";
|
||||
@ -116,7 +117,6 @@ class SendUsageTask extends AsyncTask{
|
||||
"ticks" => $server->getTick()
|
||||
];
|
||||
|
||||
|
||||
//This anonymizes the user ids so they cannot be reversed to the original
|
||||
foreach($playerList as $k => $v){
|
||||
$playerList[$k] = md5($v);
|
||||
|
@ -37,9 +37,6 @@ abstract class Task{
|
||||
return $this->taskHandler;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
final public function getTaskId() : int{
|
||||
if($this->taskHandler !== null){
|
||||
return $this->taskHandler->getTaskId();
|
||||
@ -53,7 +50,7 @@ abstract class Task{
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TaskHandler|null $taskHandler
|
||||
* @return void
|
||||
*/
|
||||
final public function setHandler(TaskHandler $taskHandler = null){
|
||||
if($this->taskHandler === null or $taskHandler === null){
|
||||
@ -64,14 +61,14 @@ abstract class Task{
|
||||
/**
|
||||
* Actions to execute when run
|
||||
*
|
||||
* @param int $currentTick
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
abstract public function onRun(int $currentTick);
|
||||
|
||||
/**
|
||||
* Actions to execute if the Task is cancelled
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function onCancel(){
|
||||
|
||||
|
@ -54,13 +54,6 @@ class TaskHandler{
|
||||
/** @var string */
|
||||
private $ownerName;
|
||||
|
||||
/**
|
||||
* @param Task $task
|
||||
* @param int $taskId
|
||||
* @param int $delay
|
||||
* @param int $period
|
||||
* @param string|null $ownerName
|
||||
*/
|
||||
public function __construct(Task $task, int $taskId, int $delay = -1, int $period = -1, ?string $ownerName = null){
|
||||
$this->task = $task;
|
||||
$this->taskId = $taskId;
|
||||
@ -72,69 +65,48 @@ class TaskHandler{
|
||||
$this->task->setHandler($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isCancelled() : bool{
|
||||
return $this->cancelled;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getNextRun() : int{
|
||||
return $this->nextRun;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $ticks
|
||||
* @return void
|
||||
*/
|
||||
public function setNextRun(int $ticks){
|
||||
$this->nextRun = $ticks;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getTaskId() : int{
|
||||
return $this->taskId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Task
|
||||
*/
|
||||
public function getTask() : Task{
|
||||
return $this->task;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getDelay() : int{
|
||||
return $this->delay;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isDelayed() : bool{
|
||||
return $this->delay > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isRepeating() : bool{
|
||||
return $this->period > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getPeriod() : int{
|
||||
return $this->period;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function cancel(){
|
||||
try{
|
||||
if(!$this->isCancelled()){
|
||||
@ -145,13 +117,16 @@ class TaskHandler{
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function remove(){
|
||||
$this->cancelled = true;
|
||||
$this->task->setHandler(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $currentTick
|
||||
* @return void
|
||||
*/
|
||||
public function run(int $currentTick){
|
||||
$this->timings->startTiming();
|
||||
@ -162,9 +137,6 @@ class TaskHandler{
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getTaskName() : string{
|
||||
return $this->taskName;
|
||||
}
|
||||
|
@ -36,14 +36,10 @@ class TaskScheduler{
|
||||
/** @var bool */
|
||||
private $enabled = true;
|
||||
|
||||
/**
|
||||
* @var ReversePriorityQueue<Task>
|
||||
*/
|
||||
/** @var ReversePriorityQueue<Task> */
|
||||
protected $queue;
|
||||
|
||||
/**
|
||||
* @var TaskHandler[]
|
||||
*/
|
||||
/** @var TaskHandler[] */
|
||||
protected $tasks = [];
|
||||
|
||||
/** @var int */
|
||||
@ -54,7 +50,6 @@ class TaskScheduler{
|
||||
|
||||
/**
|
||||
* @param \Logger $logger @deprecated
|
||||
* @param null|string $owner
|
||||
*/
|
||||
public function __construct(\Logger $logger, ?string $owner = null){
|
||||
$this->owner = $owner;
|
||||
@ -62,8 +57,6 @@ class TaskScheduler{
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Task $task
|
||||
*
|
||||
* @return TaskHandler
|
||||
*/
|
||||
public function scheduleTask(Task $task){
|
||||
@ -71,9 +64,6 @@ class TaskScheduler{
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Task $task
|
||||
* @param int $delay
|
||||
*
|
||||
* @return TaskHandler
|
||||
*/
|
||||
public function scheduleDelayedTask(Task $task, int $delay){
|
||||
@ -81,9 +71,6 @@ class TaskScheduler{
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Task $task
|
||||
* @param int $period
|
||||
*
|
||||
* @return TaskHandler
|
||||
*/
|
||||
public function scheduleRepeatingTask(Task $task, int $period){
|
||||
@ -91,10 +78,6 @@ class TaskScheduler{
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Task $task
|
||||
* @param int $delay
|
||||
* @param int $period
|
||||
*
|
||||
* @return TaskHandler
|
||||
*/
|
||||
public function scheduleDelayedRepeatingTask(Task $task, int $delay, int $period){
|
||||
@ -102,7 +85,7 @@ class TaskScheduler{
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $taskId
|
||||
* @return void
|
||||
*/
|
||||
public function cancelTask(int $taskId){
|
||||
if(isset($this->tasks[$taskId])){
|
||||
@ -114,6 +97,9 @@ class TaskScheduler{
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function cancelAllTasks(){
|
||||
foreach($this->tasks as $id => $task){
|
||||
$this->cancelTask($id);
|
||||
@ -125,20 +111,11 @@ class TaskScheduler{
|
||||
$this->ids = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $taskId
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isQueued(int $taskId) : bool{
|
||||
return isset($this->tasks[$taskId]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Task $task
|
||||
* @param int $delay
|
||||
* @param int $period
|
||||
*
|
||||
* @return TaskHandler
|
||||
*
|
||||
* @throws \InvalidStateException
|
||||
@ -185,7 +162,7 @@ class TaskScheduler{
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $currentTick
|
||||
* @return void
|
||||
*/
|
||||
public function mainThreadHeartbeat(int $currentTick){
|
||||
$this->currentTick = $currentTick;
|
||||
@ -211,9 +188,6 @@ class TaskScheduler{
|
||||
return !$this->queue->isEmpty() and $this->queue->current()->getNextRun() <= $currentTick;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
private function nextId() : int{
|
||||
return $this->ids++;
|
||||
}
|
||||
|
Reference in New Issue
Block a user