mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-06-12 14:35:35 +00:00
Added AsyncTask progress update API
This commit is contained in:
parent
bd5bbbea10
commit
e6485c4734
@ -142,8 +142,13 @@ class AsyncPool{
|
|||||||
Timings::$schedulerAsyncTimer->startTiming();
|
Timings::$schedulerAsyncTimer->startTiming();
|
||||||
|
|
||||||
foreach($this->tasks as $task){
|
foreach($this->tasks as $task){
|
||||||
|
if($task->progressUpdates !== null){
|
||||||
|
if($task->progressUpdates->count() !== 0){
|
||||||
|
$progress = $task->progressUpdates->shift();
|
||||||
|
$task->onProgressUpdate($this->server, $progress);
|
||||||
|
}
|
||||||
|
}
|
||||||
if($task->isGarbage() and !$task->isRunning() and !$task->isCrashed()){
|
if($task->isGarbage() and !$task->isRunning() and !$task->isCrashed()){
|
||||||
|
|
||||||
if(!$task->hasCancelledRun()){
|
if(!$task->hasCancelledRun()){
|
||||||
$task->onCompletion($this->server);
|
$task->onCompletion($this->server);
|
||||||
$this->server->getScheduler()->removeLocalComplex($task);
|
$this->server->getScheduler()->removeLocalComplex($task);
|
||||||
|
@ -34,6 +34,9 @@ abstract class AsyncTask extends Collectable{
|
|||||||
/** @var AsyncWorker $worker */
|
/** @var AsyncWorker $worker */
|
||||||
public $worker = null;
|
public $worker = null;
|
||||||
|
|
||||||
|
/** @var \Threaded */
|
||||||
|
public $progressUpdates = null;
|
||||||
|
|
||||||
private $result = null;
|
private $result = null;
|
||||||
private $serialized = false;
|
private $serialized = false;
|
||||||
private $cancelRun = false;
|
private $cancelRun = false;
|
||||||
@ -66,6 +69,7 @@ abstract class AsyncTask extends Collectable{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function run(){
|
public function run(){
|
||||||
|
$this->progressUpdates = new \Threaded; // Do not move this to __construct for backwards compatibility.
|
||||||
$this->result = null;
|
$this->result = null;
|
||||||
|
|
||||||
if($this->cancelRun !== true){
|
if($this->cancelRun !== true){
|
||||||
@ -169,7 +173,36 @@ abstract class AsyncTask extends Collectable{
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Call this method from {@link #onCompletion} to fetch the data stored in the constructor, if any.
|
* Call this method from {@link AsyncTask#onRun} (AsyncTask execution therad) to schedule a call to
|
||||||
|
* {@link AsyncTask#onProgressUpdate} from the main thread with the given progress parameter.
|
||||||
|
*
|
||||||
|
* @param \Threaded|mixed $progress A Threaded object, or a value that can be safely serialize()'ed.
|
||||||
|
*/
|
||||||
|
public function publishProgress($progress){
|
||||||
|
$this->progressUpdates[] = $progress;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called from the main thread after {@link AsyncTask#publishProgress} is called.
|
||||||
|
* All {@link AsyncTask#publishProgress} calls should result in {@link AsyncTask#onProgressUpdate} calls before
|
||||||
|
* {@link AsyncTask#onCompletion} is called.
|
||||||
|
*
|
||||||
|
* @param Server $server
|
||||||
|
* @param \Threaded|mixed $progress The parameter passed to {@link AsyncTask#publishProgress}. If it is not a
|
||||||
|
* Threaded object, it would be serialize()'ed and later unserialize()'ed, as if it
|
||||||
|
* has been cloned.
|
||||||
|
*/
|
||||||
|
public function onProgressUpdate(Server $server, $progress){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call this method from {@link AsyncTask#onCompletion} to fetch the data stored in the constructor, if any, and
|
||||||
|
* clears it from the storage.
|
||||||
|
*
|
||||||
|
* Do not call this method from {@link AsyncTask#onProgressUpdate}, because this method deletes the data and cannot
|
||||||
|
* be used in the next {@link AsyncTask#onProgressUpdate} call or from {@link AsyncTask#onCompletion}. Use
|
||||||
|
* {@link AsyncTask#peekLocal} instead.
|
||||||
*
|
*
|
||||||
* @param Server $server default null
|
* @param Server $server default null
|
||||||
*
|
*
|
||||||
@ -186,6 +219,28 @@ abstract class AsyncTask extends Collectable{
|
|||||||
return $server->getScheduler()->fetchLocalComplex($this);
|
return $server->getScheduler()->fetchLocalComplex($this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call this method from {@link AsyncTask#onProgressUpdate} to fetch the data stored in the constructor.
|
||||||
|
*
|
||||||
|
* Use {@link AsyncTask#peekLocal} instead from {@link AsyncTask#onCompletion}, because this method does not delete
|
||||||
|
* the data, and not clearing the data will result in a warning for memory leak after {@link AsyncTask#onCompletion}
|
||||||
|
* finished executing.
|
||||||
|
*
|
||||||
|
* @param Server|null $server default null
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*
|
||||||
|
* @throws \RuntimeException if no data were stored by this AsyncTask instance
|
||||||
|
*/
|
||||||
|
protected function peekLocal(Server $server = null){
|
||||||
|
if($server === null){
|
||||||
|
$server = Server::getInstance();
|
||||||
|
assert($server !== null, "Call this method only from the main thread!");
|
||||||
|
}
|
||||||
|
|
||||||
|
return $server->getScheduler()->peekLocalComplex($this);
|
||||||
|
}
|
||||||
|
|
||||||
public function cleanObject(){
|
public function cleanObject(){
|
||||||
foreach($this as $p => $v){
|
foreach($this as $p => $v){
|
||||||
if(!($v instanceof \Threaded)){
|
if(!($v instanceof \Threaded)){
|
||||||
|
@ -50,7 +50,7 @@ class ServerScheduler{
|
|||||||
/** @var int */
|
/** @var int */
|
||||||
protected $currentTick = 0;
|
protected $currentTick = 0;
|
||||||
|
|
||||||
/** @var \SplObjectStorage<AsyncTask> */
|
/** @var \SplObjectStorage<AsyncTask, object|array> */
|
||||||
protected $objectStore;
|
protected $objectStore;
|
||||||
|
|
||||||
public function __construct(){
|
public function __construct(){
|
||||||
@ -100,7 +100,7 @@ class ServerScheduler{
|
|||||||
*
|
*
|
||||||
* @internal Only call from AsyncTask.php
|
* @internal Only call from AsyncTask.php
|
||||||
*
|
*
|
||||||
* @param AsyncTask $for
|
* @param AsyncTask $for
|
||||||
* @param object|array $cmplx
|
* @param object|array $cmplx
|
||||||
*
|
*
|
||||||
* @throws \RuntimeException if this method is called twice for the same instance of AsyncTask
|
* @throws \RuntimeException if this method is called twice for the same instance of AsyncTask
|
||||||
@ -113,17 +113,39 @@ class ServerScheduler{
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetches data that must not be passed to other threads or be serialized, previously stored with {@link #storeLocalComplex}
|
* Fetches data that must not be passed to other threads or be serialized, previously stored with
|
||||||
|
* {@link ServerScheduler#storeLocalComplex}, without deletion of the data.
|
||||||
*
|
*
|
||||||
* @internal Only call from AsyncTask.php
|
* @internal Only call from AsyncTask.php
|
||||||
*
|
*
|
||||||
* @param AsyncTask $for
|
* @param AsyncTask $for
|
||||||
*
|
*
|
||||||
* @throws \RuntimException if no data associated with this AsyncTask can be found
|
* @return object|array
|
||||||
*/
|
*
|
||||||
|
* @throws \RuntimeException if no data associated with this AsyncTask can be found
|
||||||
|
*/
|
||||||
|
public function peekLocalComplex(AsyncTask $for){
|
||||||
|
if(!isset($this->objectStore[$for])){
|
||||||
|
throw new \RuntimeException("No local complex stored for this AsyncTask");
|
||||||
|
}
|
||||||
|
return $this->objectStore[$for];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetches data that must not be passed to other threads or be serialized, previously stored with
|
||||||
|
* {@link ServerScheduler#storeLocalComplex}, and delete the data from the storage.
|
||||||
|
*
|
||||||
|
* @internal Only call from AsyncTask.php
|
||||||
|
*
|
||||||
|
* @param AsyncTask $for
|
||||||
|
*
|
||||||
|
* @return object|array
|
||||||
|
*
|
||||||
|
* @throws \RuntimeException if no data associated with this AsyncTask can be found
|
||||||
|
*/
|
||||||
public function fetchLocalComplex(AsyncTask $for){
|
public function fetchLocalComplex(AsyncTask $for){
|
||||||
if(!isset($this->objectStore[$for])){
|
if(!isset($this->objectStore[$for])){
|
||||||
throw new \RuntimeException("Attempt to fetch undefined complex");
|
throw new \RuntimeException("No local complex stored for this AsyncTask");
|
||||||
}
|
}
|
||||||
$cmplx = $this->objectStore[$for];
|
$cmplx = $this->objectStore[$for];
|
||||||
unset($this->objectStore[$for]);
|
unset($this->objectStore[$for]);
|
||||||
@ -138,7 +160,7 @@ class ServerScheduler{
|
|||||||
* @param AsyncTask $for
|
* @param AsyncTask $for
|
||||||
*
|
*
|
||||||
* @return bool returns false if any data are removed from this call, true otherwise
|
* @return bool returns false if any data are removed from this call, true otherwise
|
||||||
*/
|
*/
|
||||||
public function removeLocalComplex(AsyncTask $for) : bool{
|
public function removeLocalComplex(AsyncTask $for) : bool{
|
||||||
if(isset($this->objectStore[$for])){
|
if(isset($this->objectStore[$for])){
|
||||||
Server::getInstance()->getLogger()->notice("AsyncTask " . get_class($for) . " stored local complex data but did not remove them after completion");
|
Server::getInstance()->getLogger()->notice("AsyncTask " . get_class($for) . " stored local complex data but did not remove them after completion");
|
||||||
|
Loading…
x
Reference in New Issue
Block a user