Merge branch 'stable' into next-minor

This commit is contained in:
Dylan K. Taylor
2020-02-10 11:40:08 +00:00
539 changed files with 3706 additions and 6211 deletions

View File

@ -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()])){

View File

@ -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){

View File

@ -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]);

View File

@ -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){

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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(){

View File

@ -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;
}

View File

@ -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++;
}