Require pthreads ^5.1

This version of pthreads has a substantially improved API, improved
performance, improved memory usage, and much less magical and broken
behaviour.
This commit is contained in:
Dylan K. Taylor
2023-01-23 20:02:33 +00:00
parent 14b250c63f
commit 222415859a
22 changed files with 245 additions and 118 deletions

View File

@ -158,7 +158,7 @@ class AsyncPool{
throw new \InvalidArgumentException("Cannot submit the same AsyncTask instance more than once");
}
$task->progressUpdates = new \Threaded();
$task->progressUpdates = new \ThreadedArray();
$task->setSubmitted();
$this->getWorker($worker)->stack($task);

View File

@ -23,11 +23,11 @@ declare(strict_types=1);
namespace pocketmine\scheduler;
use pocketmine\utils\AssumptionFailedError;
use pocketmine\thread\NonThreadSafeValue;
use function igbinary_serialize;
use function igbinary_unserialize;
use function is_null;
use function is_scalar;
use function is_string;
use function spl_object_id;
/**
@ -51,15 +51,10 @@ use function spl_object_id;
* thread, e.g. during {@link AsyncTask::onCompletion()} or {@link AsyncTask::onProgressUpdate()}. This means that
* whatever you do in onRun() must be able to work without the Server instance.
*
* WARNING: Any non-Threaded objects WILL BE SERIALIZED when assigned to members of AsyncTasks or other Threaded object.
* If later accessed from said Threaded object, you will be operating on a COPY OF THE OBJECT, NOT THE ORIGINAL OBJECT.
* If you want to store non-serializable objects to access when the task completes, store them using
* If you want to store non-thread-safe objects to access when the task completes, store them using
* {@link AsyncTask::storeLocal}.
*
* WARNING: Arrays are converted to Volatile objects when assigned as members of Threaded objects.
* Keep this in mind when using arrays stored as members of your AsyncTask.
*/
abstract class AsyncTask extends \Threaded{
abstract class AsyncTask extends \ThreadedRunnable{
/**
* @var \ArrayObject|mixed[]|null object hash => mixed data
* @phpstan-var \ArrayObject<int, array<string, mixed>>|null
@ -71,10 +66,11 @@ abstract class AsyncTask extends \Threaded{
/** @var AsyncWorker|null $worker */
public $worker = null;
public \Threaded $progressUpdates;
/** @phpstan-var \ThreadedArray<int, string> */
public \ThreadedArray $progressUpdates;
private string|int|bool|null|float $result = null;
private bool $serialized = false;
/** @phpstan-var NonThreadSafeValue<mixed>|string|int|bool|float|null */
private NonThreadSafeValue|string|int|bool|null|float $result = null;
private bool $cancelRun = false;
private bool $submitted = false;
@ -117,15 +113,14 @@ abstract class AsyncTask extends \Threaded{
* @return mixed
*/
public function getResult(){
if($this->serialized){
if(!is_string($this->result)) throw new AssumptionFailedError("Result expected to be a serialized string");
return igbinary_unserialize($this->result);
if($this->result instanceof NonThreadSafeValue){
return $this->result->deserialize();
}
return $this->result;
}
public function setResult(mixed $result) : void{
$this->result = ($this->serialized = !is_scalar($result)) ? igbinary_serialize($result) : $result;
$this->result = is_scalar($result) || is_null($result) ? $result : new NonThreadSafeValue($result);
}
public function cancelRun() : void{
@ -164,15 +159,14 @@ abstract class AsyncTask extends \Threaded{
* @param mixed $progress A value that can be safely serialize()'ed.
*/
public function publishProgress(mixed $progress) : void{
$this->progressUpdates[] = igbinary_serialize($progress);
$this->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($this->progressUpdates->count() !== 0){
$progress = $this->progressUpdates->shift();
while(($progress = $this->progressUpdates->shift()) !== null){
$this->onProgressUpdate(igbinary_unserialize($progress));
}
}