mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-04-21 08:17:34 +00:00
AsyncTask: lazy-init progressUpdates (#5806)
this is only possible since pthreads 5.1 and pmmpthread the performance cost of this one ThreadSafeArray allocation is 30% of the total cost of allocating an AsyncTask object on Windows, which is enormous. In past versions we couldn't lazily initialize it, because the object might get destroyed before the main thread had a chance to dereference it, leading to a crash when collecting completed tasks. This is no longer an issue thanks to object rescue behaviour implemented in pthreads 5.1. I think this is probably OK in terms of thread-safety, as only one thread writes the property.
This commit is contained in:
parent
1b35c352cc
commit
df4a8d4788
@ -24,7 +24,6 @@ declare(strict_types=1);
|
||||
namespace pocketmine\scheduler;
|
||||
|
||||
use pmmp\thread\Thread as NativeThread;
|
||||
use pmmp\thread\ThreadSafeArray;
|
||||
use pocketmine\snooze\SleeperHandler;
|
||||
use pocketmine\thread\log\ThreadSafeLogger;
|
||||
use pocketmine\thread\ThreadSafeClassLoader;
|
||||
@ -146,7 +145,6 @@ class AsyncPool{
|
||||
throw new \InvalidArgumentException("Cannot submit the same AsyncTask instance more than once");
|
||||
}
|
||||
|
||||
$task->progressUpdates = new ThreadSafeArray();
|
||||
$task->setSubmitted();
|
||||
|
||||
$this->getWorker($worker)->submit($task);
|
||||
|
@ -68,8 +68,8 @@ abstract class AsyncTask extends Runnable{
|
||||
*/
|
||||
private static ?\ArrayObject $threadLocalStorage = null;
|
||||
|
||||
/** @phpstan-var ThreadSafeArray<int, string> */
|
||||
public ThreadSafeArray $progressUpdates;
|
||||
/** @phpstan-var ThreadSafeArray<int, string>|null */
|
||||
private ?ThreadSafeArray $progressUpdates = null;
|
||||
|
||||
private ThreadSafe|string|int|bool|null|float $result = null;
|
||||
private bool $cancelRun = false;
|
||||
@ -163,15 +163,22 @@ abstract class AsyncTask extends Runnable{
|
||||
* @param mixed $progress A value that can be safely serialize()'ed.
|
||||
*/
|
||||
public function publishProgress(mixed $progress) : void{
|
||||
$this->progressUpdates[] = igbinary_serialize($progress) ?? throw new \InvalidArgumentException("Progress must be serializable");
|
||||
$progressUpdates = $this->progressUpdates;
|
||||
if($progressUpdates === null){
|
||||
$progressUpdates = $this->progressUpdates = new ThreadSafeArray();
|
||||
}
|
||||
$progressUpdates[] = igbinary_serialize($progress) ?? throw new \InvalidArgumentException("Progress must be serializable");
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal Only call from AsyncPool.php on the main thread
|
||||
*/
|
||||
public function checkProgressUpdates() : void{
|
||||
while(($progress = $this->progressUpdates->shift()) !== null){
|
||||
$this->onProgressUpdate(igbinary_unserialize($progress));
|
||||
$progressUpdates = $this->progressUpdates;
|
||||
if($progressUpdates !== null){
|
||||
while(($progress = $progressUpdates->shift()) !== null){
|
||||
$this->onProgressUpdate(igbinary_unserialize($progress));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user