PocketMine-MP 5.15.1 git-fb9a74e8799c71ed8292cfa53abe7a4c9204629d
AsyncTask.php
1<?php
2
3/*
4 *
5 * ____ _ _ __ __ _ __ __ ____
6 * | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
7 * | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
8 * | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
9 * |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
10 *
11 * This program is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License as published by
13 * the Free Software Foundation, either version 3 of the License, or
14 * (at your option) any later version.
15 *
16 * @author PocketMine Team
17 * @link http://www.pocketmine.net/
18 *
19 *
20 */
21
22declare(strict_types=1);
23
24namespace pocketmine\scheduler;
25
26use pmmp\thread\Runnable;
27use pmmp\thread\ThreadSafe;
28use pmmp\thread\ThreadSafeArray;
30use function array_key_exists;
31use function igbinary_serialize;
32use function igbinary_unserialize;
33use function is_null;
34use function is_scalar;
35use function spl_object_id;
36
61abstract class AsyncTask extends Runnable{
68 private static array $threadLocalStorage = [];
69
71 private ?ThreadSafeArray $progressUpdates = null;
72
73 private ThreadSafe|string|int|bool|null|float $result = null;
74
75 private bool $submitted = false;
76 private bool $finished = false;
77
78 public function run() : void{
79 $this->result = null;
80
81 $this->onRun();
82
83 $this->finished = true;
84 AsyncWorker::getNotifier()->wakeupSleeper();
85 }
86
90 public function isCrashed() : bool{
91 return $this->isTerminated();
92 }
93
98 public function isFinished() : bool{
99 return $this->finished || $this->isTerminated();
100 }
101
102 public function hasResult() : bool{
103 return $this->result !== null;
104 }
105
109 public function getResult(){
110 if($this->result instanceof NonThreadSafeValue){
111 return $this->result->deserialize();
112 }
113 return $this->result;
114 }
115
116 public function setResult(mixed $result) : void{
117 $this->result = is_scalar($result) || is_null($result) || $result instanceof ThreadSafe ? $result : new NonThreadSafeValue($result);
118 }
119
123 public function cancelRun() : void{
124 //NOOP
125 }
126
130 public function hasCancelledRun() : bool{
131 return false;
132 }
133
134 public function setSubmitted() : void{
135 $this->submitted = true;
136 }
137
138 public function isSubmitted() : bool{
139 return $this->submitted;
140 }
141
145 abstract public function onRun() : void;
146
151 public function onCompletion() : void{
152
153 }
154
161 public function publishProgress(mixed $progress) : void{
162 $progressUpdates = $this->progressUpdates;
163 if($progressUpdates === null){
164 $progressUpdates = $this->progressUpdates = new ThreadSafeArray();
165 }
166 $progressUpdates[] = igbinary_serialize($progress) ?? throw new \InvalidArgumentException("Progress must be serializable");
167 }
168
172 public function checkProgressUpdates() : void{
173 $progressUpdates = $this->progressUpdates;
174 if($progressUpdates !== null){
175 while(($progress = $progressUpdates->shift()) !== null){
176 $this->onProgressUpdate(igbinary_unserialize($progress));
177 }
178 }
179 }
180
189 public function onProgressUpdate($progress) : void{
190
191 }
192
196 public function onError() : void{
197
198 }
199
214 protected function storeLocal(string $key, mixed $complexData) : void{
215 self::$threadLocalStorage[spl_object_id($this)][$key] = $complexData;
216 }
217
228 protected function fetchLocal(string $key){
229 $id = spl_object_id($this);
230 if(!isset(self::$threadLocalStorage[$id]) || !array_key_exists($key, self::$threadLocalStorage[$id])){
231 throw new \InvalidArgumentException("No matching thread-local data found on this thread");
232 }
233
234 return self::$threadLocalStorage[$id][$key];
235 }
236
237 final public function __destruct(){
238 $this->reallyDestruct();
239 unset(self::$threadLocalStorage[spl_object_id($this)]);
240 }
241
245 protected function reallyDestruct() : void{
246
247 }
248}