diff --git a/src/PocketMine/Server.php b/src/PocketMine/Server.php index 3965dace5..26d7046a1 100644 --- a/src/PocketMine/Server.php +++ b/src/PocketMine/Server.php @@ -673,7 +673,9 @@ class Server{ $level->unload(true); } - $this->scheduler->shutdown(); + $this->scheduler->cancelAllTasks(); + $this->scheduler->mainThreadHeartbeat(PHP_INT_MAX); + $this->tickScheduler->kill(); $this->console->kill(); diff --git a/src/PocketMine/scheduler/ServerWorker.php b/src/PocketMine/scheduler/CallbackTask.php similarity index 54% rename from src/PocketMine/scheduler/ServerWorker.php rename to src/PocketMine/scheduler/CallbackTask.php index f87558ab4..1b643e687 100644 --- a/src/PocketMine/scheduler/ServerWorker.php +++ b/src/PocketMine/scheduler/CallbackTask.php @@ -21,43 +21,36 @@ namespace PocketMine\Scheduler; -use PocketMine\Plugin\Plugin; - -class ServerWorker{ - private $asyncTask; - private $thread; +/** + * Allows the creation if simple callbacks with extra data + * The last parameter in the callback will be this object + * + * If you want to do a task in a Plugin, consider extending PluginTask to your needs + */ +class CallbackTask extends Task{ /** - * @param ServerAsyncTask $asyncTask - * @param \Thread $thread + * @var callable */ - public function __construct(ServerAsyncTask $asyncTask, \Thread $thread){ - $this->asyncTask = $asyncTask; - $this->thread = $thread; - } - - public function __destruct(){ - unset($this->asyncTask, $this->thread); - } + protected $callable; /** - * @return int + * @var array */ - public function getTaskId(){ - return $this->asyncTask->getTaskId(); - } + protected $args; /** - * @return Plugin; + * @param callable $callable + * @param array $args */ - public function getOwner(){ - return $this->asyncTask->getOwner(); + public function __construct(callable $callable, array $args){ + $this->callable = $callable; + $this->args = $args; + $this->args[] = $this; } - /** - * @return \Thread - */ - public function getThread(){ - //TODO + public function onRun($currentTicks){ + call_user_func_array($this->callable, $this->args); } -} \ No newline at end of file + +} diff --git a/src/PocketMine/scheduler/ServerCallable.php b/src/PocketMine/scheduler/PluginTask.php similarity index 64% rename from src/PocketMine/scheduler/ServerCallable.php rename to src/PocketMine/scheduler/PluginTask.php index 9223b150b..2b21aff38 100644 --- a/src/PocketMine/scheduler/ServerCallable.php +++ b/src/PocketMine/scheduler/PluginTask.php @@ -21,14 +21,30 @@ namespace PocketMine\Scheduler; +use PocketMine\Plugin\Plugin; -abstract class ServerCallable extends ServerTask{ +/** + * Base class for plugin tasks. Allows the Server to delete them easily when needed + */ +abstract class PluginTask extends Task{ /** - * Returns the computation result if finished, or null - * - * @return mixed|null + * @var Plugin */ - public abstract function getResult(); + protected $owner; -} \ No newline at end of file + /** + * @param Plugin $owner + */ + public function __construct(Plugin $owner){ + $this->owner = $owner; + } + + /** + * @return Plugin + */ + public final function getOwner(){ + return $this->owner; + } + +} diff --git a/src/PocketMine/scheduler/ServerAllTaskCanceller.php b/src/PocketMine/scheduler/ServerAllTaskCanceller.php deleted file mode 100644 index 565ed5f23..000000000 --- a/src/PocketMine/scheduler/ServerAllTaskCanceller.php +++ /dev/null @@ -1,81 +0,0 @@ -temp = $temp; - $this->pending = $pending; - $this->runners = $runners; - } - - public function run(){ - foreach($this->runners as $index => $task){ - $task->cancel0(); - if($task->isSync()){ - unset($this->runners[$index]); - } - } - while($this->temp->count() > 0){ - $this->temp->pop(); - } - while($this->pending->count() > 0){ - $this->pending->pop(); - } - } - - /** - * @param ServerTask[] $collection - * - * @return bool - */ - private function check($collection){ - foreach($collection as $index => $task){ - if($task->getTaskId() === $this->taskId){ - $task->cancel0(); - unset($collection[$index]); - if($task->isSync()){ - unset($this->runners[$this->taskId]); - } - return true; - } - } - return false; - } - -} \ No newline at end of file diff --git a/src/PocketMine/scheduler/ServerAsyncTask.php b/src/PocketMine/scheduler/ServerAsyncTask.php deleted file mode 100644 index 39d88e45a..000000000 --- a/src/PocketMine/scheduler/ServerAsyncTask.php +++ /dev/null @@ -1,101 +0,0 @@ - - */ - private $workers; - - /** - * @var \Threaded - */ - private $runners; - - - public function __construct(\Threaded $runners, Plugin $plugin, \Threaded $task, $id, $delay){ - parent::__construct($plugin, $task, $id, $delay); - $this->runners = $runners; - $this->workers = new \Threaded(); - } - - public function isSync(){ - return false; - } - - public function run(){ - $thread = \Thread::getCurrentThread(); - $this->workers->synchronized(function($workers, \Thread $thread, ServerAsyncTask $asyncTask){ - if($asyncTask->getPeriod() === -2){ - return; - } - $workers[] = new ServerWorker($asyncTask, $thread); - }, $thread, $this); - - parent::run(); - - $this->workers->synchronized(function(\Threaded $workers, \Threaded $runners, \Thread $thread){ - $removed = false; - foreach($workers as $index => $worker){ - if($worker->getThread() === $thread){ - unset($workers[$index]); - $removed = true; - break; - } - } - - if(!$removed){ - trigger_error("Unable to remove worker ".$thread->getThreadId()." on task ".$this->getTaskId()." for ".$this->getOwner()->getDescription()->getName(), E_USER_WARNING); - } - - if($this->getPeriod() < 0 and $this->workers->count() === 0){ - unset($runners[$this->getTaskId()]); - } - }, $this->workers, $this->runners, $thread); - } - - /** - * @return \Threaded - */ - public function getWorkers(){ - return $this->workers; - } - - /** - * @return bool - */ - public function cancel0(){ - $this->workers->synchronized(function(ServerAsyncTask $asyncTask, \Threaded $runners, \Threaded $workers){ - $asyncTask->setPeriod(-2); - if($workers->count() === 0){ - unset($runners[$asyncTask->getTaskId()]); - } - }, $this, $this->runners, $this->workers); - return true; - } - - -} \ No newline at end of file diff --git a/src/PocketMine/scheduler/ServerFuture.php b/src/PocketMine/scheduler/ServerFuture.php deleted file mode 100644 index b90160829..000000000 --- a/src/PocketMine/scheduler/ServerFuture.php +++ /dev/null @@ -1,127 +0,0 @@ -callable = $callable; - } - - public function cancel(){ - if($this->getPeriod() !== -1){ - return false; - } - $this->setPeriod(-2); - return true; - } - - public function isCancelled(){ - return $this->getPeriod() === -2; - } - - public function isDone(){ - return $this->getPeriod() !== -1 and $this->getPeriod() !== -3; - } - - /** - * @param int $timeout Microseconds to wait - * - * @return mixed|null - */ - public function get($timeout){ - $period = $this->getPeriod(); - $timestamp = $timeout > 0 ? (int) (microtime(true) / 1000000) : 0; - - while(true){ - if($period === -1 or $period === -3){ - $this->wait($timeout); - $period = $this->getPeriod(); - if($period === -1 or $period === -3){ - if($timeout === 0){ - continue; - } - $timeout += $timestamp - ($timestamp = (int) (microtime(true) / 1000000)); - - if($timeout > 0){ - continue; - } - return null; - } - } - if($period === -2){ - return null; //Cancelled - } - if($period === -4){ - return $this->value; - } - return null; //Invalid state - } - } - - public function run(){ - if($this->synchronized(function(ServerFuture $future){ - if($future->getPeriod() === -2){ - return false; - } - $future->setPeriod(-3); - return true; - }, $this) === false){ - return; - } - - $this->callable->run(); - $this->value = $this->callable->getResult(); - - $this->synchronized(function(ServerFuture $future){ - $future->setPeriod(-4); - $future->notify(); - }, $this); - } - - public function cancel0(){ - if($this->getPeriod() !== -1){ - return false; - } - $this->setPeriod(-2); - $this->notify(); - return true; - } -} \ No newline at end of file diff --git a/src/PocketMine/scheduler/ServerPluginTaskCanceller.php b/src/PocketMine/scheduler/ServerPluginTaskCanceller.php deleted file mode 100644 index c153f65cd..000000000 --- a/src/PocketMine/scheduler/ServerPluginTaskCanceller.php +++ /dev/null @@ -1,79 +0,0 @@ -plugin = $plugin; - $this->temp = $temp; - $this->pending = $pending; - $this->runners = $runners; - } - - public function run(){ - $this->check($this->temp); - $this->check($this->pending); - } - - /** - * @param ServerTask[] $collection - * - * @return bool - */ - private function check($collection){ - foreach($collection as $index => $task){ - if($task->getOwner() === $this->plugin){ - $task->cancel0(); - unset($collection[$index]); - if($task->isSync()){ - unset($this->runners[$task->getTaskId()]); - } - return true; - } - } - return false; - } - -} \ No newline at end of file diff --git a/src/PocketMine/scheduler/ServerRunnable.php b/src/PocketMine/scheduler/ServerRunnable.php deleted file mode 100644 index 46ab9c506..000000000 --- a/src/PocketMine/scheduler/ServerRunnable.php +++ /dev/null @@ -1,151 +0,0 @@ -cancelTask($this->getTaskId()); - } - - /** - * Runs the task on the next tick - * - * @param Plugin $plugin - * - * @return ServerTask|null - */ - public function runTask(Plugin $plugin){ - if($this->checkState()){ - return $this->setupId(ServerScheduler::getInstance()->runTask($plugin, $this)); - } - return null; - } - - /** - * Schedules the task to run asynchronously - * - * @param Plugin $plugin - * - * @return ServerTask|null - */ - public function runTaskAsynchronously(Plugin $plugin){ - if($this->checkState()){ - return $this->setupId(ServerScheduler::getInstance()->runTaskAsynchronously($plugin, $this)); - } - return null; - } - - /** - * Runs the task after a number of server ticks - * - * @param Plugin $plugin - * @param int $delay - * - * @return ServerTask|null - */ - public function runTaskLater(Plugin $plugin, $delay){ - if($this->checkState()){ - return $this->setupId(ServerScheduler::getInstance()->runTaskLater($plugin, $this, $delay)); - } - return null; - } - - /** - * @param Plugin $plugin - * @param int $delay - * - * @return ServerTask|null - */ - public function runTaskLaterAsynchronously(Plugin $plugin, $delay){ - if($this->checkState()){ - return $this->setupId(ServerScheduler::getInstance()->runTaskLaterAsynchronously($plugin, $this, $delay)); - } - return null; - } - - /** - * @param Plugin $plugin - * @param int $delay - * @param int $period - * - * @return ServerTask|null - */ - public function runTaskTimer(Plugin $plugin, $delay, $period){ - if($this->checkState()){ - return $this->setupId(ServerScheduler::getInstance()->runTaskTimer($plugin, $this, $delay, $period)); - } - return null; - } - - /** - * @param Plugin $plugin - * @param int $delay - * @param int $period - * - * @return ServerTask|null - */ - public function runTaskTimerAsynchronously(Plugin $plugin, $delay, $period){ - if($this->checkState()){ - return $this->setupId(ServerScheduler::getInstance()->runTaskTimerAsynchronously($plugin, $this, $delay, $period)); - } - return null; - } - - /** - * @return int - */ - public function getTaskId(){ - if($this->taskId === -1){ - return -1; - } - return $this->taskId; - } - - - public function checkState(){ - if($this->taskId !== -1){ - return false; - } - return true; - } - - public function setupId(ServerTask $task){ - if($task !== null){ - $this->taskId = $task->getTaskId(); - } - return $task; - } - - -} \ No newline at end of file diff --git a/src/PocketMine/scheduler/ServerScheduler.php b/src/PocketMine/scheduler/ServerScheduler.php index 26586f790..9710e38b3 100644 --- a/src/PocketMine/scheduler/ServerScheduler.php +++ b/src/PocketMine/scheduler/ServerScheduler.php @@ -22,254 +22,80 @@ namespace PocketMine\Scheduler; use PocketMine\Plugin\Plugin; -use PocketMine\Server; class ServerScheduler{ /** - * @var ServerScheduler + * @var \SplPriorityQueue */ - private static $instance = null; - - private $ids = 1; + protected $queue; /** - * @var ServerTask + * @var TaskHandler[] */ - private $head; - - /** - * @var ServerTask - */ - private $tail; - - /** - * @var \SplPriorityQueue - */ - private $pending; - - /** - * @var ServerTask[] - */ - private $temp = array(); - - /** - * @var ServerTask[] - */ - private $runners; + protected $tasks = array(); /** * @var int */ - private $currentTick = -1; + private $ids = 1; /** - * @var \Pool[] + * @var int */ - private $executor; + protected $currentTick = 0; - /** - * @return ServerScheduler - */ - public static function getInstance(){ - return self::$instance; + public function __construct(){ + $this->queue = new \SplPriorityQueue(); } /** - * @param int $workers - */ - public function __construct($workers = 8){ - self::$instance = $this; - $this->head = new ServerTask(); - $this->tail = new ServerTask(); - $this->pending = new \SplPriorityQueue(); - $this->temp = array(); - $this->runners = new \Threaded(); - $this->executor = new TaskPool($workers); - - } - - public function shutdown(){ - $this->mainThreadHeartbeat($this->currentTick + 1); - $this->executor->shutdown(); - } - - /** - * @param Plugin $plugin - * @param \Threaded $task - * @param int $delay + * @param Task $task * - * @return int taskId + * @return null|TaskHandler */ - public function scheduleSyncDelayedTask(Plugin $plugin, \Threaded $task, $delay = 0){ - return $this->scheduleSyncRepeatingTask($plugin, $task, $delay, -1); + public function scheduleTask(Task $task){ + return $this->addTask($task, -1, -1); } /** - * @param Plugin $plugin - * @param \Threaded $task - * @param int $delay + * @param Task $task + * @param int $delay * - * @return int taskId + * @return null|TaskHandler */ - public function scheduleAsyncDelayedTask(Plugin $plugin, \Threaded $task, $delay = 0){ - return $this->scheduleAsyncRepeatingTask($plugin, $task, $delay, -1); + public function scheduleDelayedTask(Task $task, $delay){ + return $this->addTask($task, (int) $delay, -1); } /** - * @param Plugin $plugin - * @param \Threaded $task + * @param Task $task + * @param int $period * - * @return ServerTask|null + * @return null|TaskHandler */ - public function runTaskAsynchronously(Plugin $plugin, \Threaded $task){ - return $this->runTaskLaterAsynchronously($plugin, $task, 0); + public function scheduleRepeatingTask(Task $task, $period){ + return $this->addTask($task, -1, (int) $period); } /** - * @param Plugin $plugin - * @param \Threaded $task + * @param Task $task + * @param int $delay + * @param int $period * - * @return ServerTask|null + * @return null|TaskHandler */ - public function runTask(Plugin $plugin, \Threaded $task){ - return $this->runTaskLater($plugin, $task, 0); - } - - /** - * @param Plugin $plugin - * @param \Threaded $task - * @param int $delay - * - * @return ServerTask|null - */ - public function runTaskLater(Plugin $plugin, \Threaded $task, $delay = 0){ - return $this->runTaskTimer($plugin, $task, $delay, -1); - } - - /** - * @param Plugin $plugin - * @param \Threaded $task - * @param int $delay - * - * @return ServerTask|null - */ - public function runTaskLaterAsynchronously(Plugin $plugin, \Threaded $task, $delay){ - return $this->runTaskTimerAsynchronously($plugin, $task, $delay, -1); - } - - /** - * @param Plugin $plugin - * @param \Threaded $task - * @param int $delay - * @param int $period - * - * @return int taskId - */ - public function scheduleSyncRepeatingTask(Plugin $plugin, \Threaded $task, $delay, $period){ - return $this->runTaskTimer($plugin, $task, $delay, $period)->getTaskId(); - } - - /** - * @param Plugin $plugin - * @param \Threaded $task - * @param int $delay - * @param int $period - * - * @return int taskId - */ - public function scheduleAsyncRepeatingTask(Plugin $plugin, \Threaded $task, $delay, $period){ - return $this->runTaskTimerAsynchronously($plugin, $task, $delay, $period)->getTaskId(); - } - - /** - * @param Plugin $plugin - * @param \Threaded $task - * @param int $delay - * @param int $period - * - * @return ServerTask|null - */ - public function runTaskTimer(Plugin $plugin, \Threaded $task, $delay, $period){ - if(!$this->validate($plugin, $task)){ - return null; - } - - if($delay < 0){ - $delay = 0; - } - - if($period === 0){ - $period = 1; - }elseif($period < -1){ - $period = -1; - } - - return $this->handle(new ServerTask($plugin, $task, $this->nextId(), $period), $delay); - } - - /** - * @param Plugin $plugin - * @param \Threaded $task - * @param int $delay - * @param int $period - * - * @return ServerTask|null - */ - public function runTaskTimerAsynchronously(Plugin $plugin, \Threaded $task, $delay, $period){ - if(!$this->validate($plugin, $task)){ - return null; - } - - if($delay < 0){ - $delay = 0; - } - - if($period === 0){ - $period = 1; - }elseif($period < -1){ - $period = -1; - } - - return $this->handle(new ServerAsyncTask($this->runners, $plugin, $task, $this->nextId(), $period), $delay); - } - - /** - * @param Plugin $plugin - * @param ServerCallable $task - * - * @return ServerFuture|null - */ - public function callSyncMethod(Plugin $plugin, ServerCallable $task){ - if(!$this->validate($plugin, $task)){ - return null; - } - $future = new ServerFuture($task, $plugin, $this->nextId()); - $this->handle($future, 0); - return $future; + public function scheduleDelayedRepeatingTask(Task $task, $delay, $period){ + return $this->addTask($task, (int) $delay, (int) $period); } /** * @param int $taskId */ public function cancelTask($taskId){ - if($taskId < 0){ - return; - } - - if(isset($this->runners[$taskId])){ - $this->runners[$taskId]->cancel0(); - } - - $task = new ServerTask(null, new ServerTaskCanceller($taskId, $this->temp, $this->pending, $this->runners)); - $this->handle($task, 0); - for($taskPending = $this->head->getNext(); $taskPending !== null; $taskPending = $taskPending->getNext()){ - if($taskPending === $task){ - return; - } - if($taskPending->getTaskId() === $taskId){ - $taskPending->cancel0(); - } + if(isset($this->tasks[$taskId])){ + $this->tasks[$taskId]->cancel(); + unset($this->tasks[$taskId]); } } @@ -277,60 +103,19 @@ class ServerScheduler{ * @param Plugin $plugin */ public function cancelTasks(Plugin $plugin){ - if($plugin === null){ - return; - } - - $task = new ServerTask(null, new ServerPluginTaskCanceller($plugin, $this->temp, $this->pending, $this->runners)); - $this->handle($task, 0); - for($taskPending = $this->head->getNext(); $taskPending !== null; $taskPending = $taskPending->getNext()){ - if($taskPending === $task){ - return; - } - if($taskPending->getTaskId() !== -1 and $taskPending->getOwner() === $plugin){ - $taskPending->cancel0(); - } - } - - foreach($this->runners as $runner){ - if($runner->getOwner() === $plugin){ - $runner->cancel0(); + foreach($this->tasks as $taskId => $task){ + if($task->getTask() instanceof PluginTask){ + $task->cancel(); + unset($this->tasks[$taskId]); } } } - /** - * - */ public function cancelAllTasks(){ - $task = new ServerTask(null, new ServerAllTaskCanceller($this->temp, $this->pending, $this->runners)); - $this->handle($task, 0); - for($taskPending = $this->head->getNext(); $taskPending !== null; $taskPending = $taskPending->getNext()){ - if($taskPending === $task){ - break; - } - $taskPending->cancel0(); + foreach($this->tasks as $task){ + $task->cancel(); } - - foreach($this->runners as $runner){ - $runner->cancel0(); - } - } - - /** - * @param int $taskId - * - * @return bool - */ - public function isCurrentlyRunning($taskId){ - if(!isset($this->runners[$taskId]) or $this->runners[$taskId]->isSync()){ - return false; - } - - $asyncTask = $this->runners[$taskId]; - return $asyncTask->syncronized(function($asyncTask){ - return count($asyncTask->getWorkers()) === 0; - }, $asyncTask); + $this->tasks = array(); } /** @@ -339,69 +124,40 @@ class ServerScheduler{ * @return bool */ public function isQueued($taskId){ - if($taskId <= 0){ - return false; - } - - for($task = $this->head->getNext(); $task !== null; $task = $task->getNext()){ - if($task->getTaskId() === $taskId){ - return $task->getPeriod() >= -1; - } - } - - if(isset($this->runners[$taskId])){ - return $this->runners[$taskId]->getPeriod() >= -1; - } - return false; + return isset($this->tasks[$taskId]); } - /** - * @return ServerWorker[] - */ - public function getActiveWorkers(){ - $workers = array();//new \Threaded(); - - foreach($this->runners as $taskObj){ - if($taskObj->isSync()){ - continue; - } - - $taskObj->syncronized(function($workers, $taskObj){ - foreach($taskObj->getWorkers() as $worker){ - $workers[] = $worker; - } - }, $workers, $taskObj); + private function addTask(Task $task, $delay, $period){ + if($task instanceof PluginTask and !$task->getOwner()->isEnabled()){ + trigger_error("Plugin attempted to register a task while disabled", E_USER_WARNING); + return null; } - //$workers->run(); //Protect against memory leaks - return $workers; + if($delay <= 0){ + $delay = -1; + } + + if($period === 1){ + $period = 1; + }elseif($period < -1){ + $period = -1; + } + + return $this->handle(new TaskHandler($task, $this->nextId(), $delay, $period)); } - /** - * @return ServerTask[] - */ - public function getPendingTasks(){ - $truePending = array(); - for($task = $this->head->getNext(); $task !== null; $task = $task->getNext()){ - if($task->getTaskId() !== -1){ - $truePending[] = $task; - } + private function handle(TaskHandler $handler){ + if($handler->isDelayed()){ + $nextRun = $this->currentTick + $handler->getDelay(); + }else{ + $nextRun = $this->currentTick; } - $pending = array(); - foreach($this->runners as $task){ - if($task->getPeriod() >= -1){ - $pending[] = $task; - } - } + $handler->setNextRun($nextRun); + $this->tasks[$handler->getTaskId()] = $handler; + $this->queue->insert($handler, $nextRun); - foreach($truePending as $task){ - if($task->getPeriod() >= -1 and !in_array($pending, $task, true)){ - $pending[] = $task; - } - } - - return $pending; + return $handler; } /** @@ -409,73 +165,27 @@ class ServerScheduler{ */ public function mainThreadHeartbeat($currentTick){ $this->currentTick = $currentTick; - $this->parsePending(); - while($this->isReady($currentTick)){ - $task = $this->pending->extract(); - if($task->getPeriod() < -1){ - if($task->isSync()){ - unset($this->runners[$task->getTaskId()]); - } - $this->parsePending(); + while($this->isReady($this->currentTick)){ + $task = $this->queue->extract(); + if($task->isCancelled()){ + unset($this->tasks[$task->getTaskId()]); continue; - } - - if($task->isSync()){ - $task->run(); }else{ - $this->executor->submit($task); + $task->run(); } - - $period = $task->getPeriod(); - if($period > 0){ - $task->setNextRun($currentTick + $period); - $this->temp[] = $task; - }elseif($task->isSync()){ - unset($this->runners[$task->getTaskId()]); + if($task->isRepeating()){ + $task->setNextRun($this->currentTick + $task->getPeriod()); + $this->queue->insert($task, $this->currentTick + $task->getPeriod()); + }else{ + $task->remove(); + unset($this->tasks[$task->getTaskId()]); } } - - foreach($this->temp as $task){ - $this->pending->insert($task, $task->getNextRun()); - } - $this->temp = array(); - } - /** - * @param ServerTask $task - */ - private function addTask(ServerTask $task){ - $this->tail->setNext($task); - $this->tail = $task; - } - - /** - * @param ServerTask $task - * @param int $delay - * - * @return ServerTask - */ - private function handle(ServerTask $task, $delay){ - $task->setNextRun($this->currentTick + $delay); - $this->addTask($task); - return $task; - } - - /** - * @param Plugin $plugin - * @param \Threaded $task - * - * @return bool - */ - private function validate(Plugin $plugin, \Threaded $task){ - if($plugin === null or $task === null){ - return false; - }elseif(!$plugin->isEnabled()){ - return false; - } - return true; + private function isReady($currentTicks){ + return count($this->tasks) > 0 and $this->queue->current()->getNextRun() <= $currentTicks; } /** @@ -485,33 +195,4 @@ class ServerScheduler{ return $this->ids++; } - private function parsePending(){ - $head = $this->head; - $task = $head->getNext(); - $lastTask = $head; - for(; $task !== null; $task = $lastTask->getNext()){ - if($task->getTaskId() === -1){ - $task->run(); - }elseif($task->getPeriod() >= -1){ - $this->pending[] = $task; - $this->runners[$task->getTaskId()] = $task; - } - $lastTask = $task; - } - - for($task = $head; $task !== $lastTask; $task = $head){ - $head = $task->getNext(); - $task->setNext(null); - } - $this->head = $lastTask; - } - - /** - * @param int $currentTick - * - * @return bool - */ - private function isReady($currentTick){ - return $this->pending->count() > 0 and $this->pending->top()->getNextRun() <= $currentTick; - } } diff --git a/src/PocketMine/scheduler/ServerTask.php b/src/PocketMine/scheduler/ServerTask.php deleted file mode 100644 index f2d65c83d..000000000 --- a/src/PocketMine/scheduler/ServerTask.php +++ /dev/null @@ -1,131 +0,0 @@ -0 means number of ticks to wait between each execution - * - * @var int - */ - private $period; - private $nextRun; - - /** - * @var \Threaded; - */ - private $task; - /** - * @var Plugin - */ - private $plugin; - - /** - * @var int - */ - private $id; - - public function __construct(Plugin $plugin = null, \Threaded $task = null, $id = -1, $period = -1){ - $this->plugin = $plugin; - $this->task = $task; - $this->id = $id; - $this->period = $period; - } - - /** - * @return int - */ - public function getTaskId(){ - return $this->id; - } - - /** - * @return Plugin - */ - public function getOwner(){ - return $this->plugin; - } - - public function isSync(){ - return true; - } - - public function run(){ - $this->task->run(); - } - - public function getPeriod(){ - return $this->period; - } - - /** - * @param int $period - */ - public function setPeriod($period){ - $this->period = $period; - } - - public function getNextRun(){ - return $this->nextRun; - } - - public function setNextRun($nextRun){ - $this->nextRun = $nextRun; - } - - /** - * @return ServerTask - */ - public function getNext(){ - return $this->next; - } - - public function setNext(ServerTask $next){ - $this->next = $next; - } - - public function getTaskClass(){ - return get_class($this->next); - } - - public function cancel(){ - ServerScheduler::getInstance()->cancelTask($this->id); - } - - public function cancel0(){ - $this->setPeriod(-2); - return true; - } - - -} \ No newline at end of file diff --git a/src/PocketMine/scheduler/ServerTaskCanceller.php b/src/PocketMine/scheduler/ServerTaskCanceller.php deleted file mode 100644 index 98c5279e6..000000000 --- a/src/PocketMine/scheduler/ServerTaskCanceller.php +++ /dev/null @@ -1,73 +0,0 @@ -taskId = $taskId; - $this->temp = $temp; - $this->pending = $pending; - $this->runners = $runners; - } - - public function run(){ - if(!$this->check($this->temp)){ - $this->check($this->pending); - } - } - - /** - * @param ServerTask[] $collection - * - * @return bool - */ - private function check($collection){ - foreach($collection as $index => $task){ - if($task->getTaskId() === $this->taskId){ - $task->cancel0(); - unset($collection[$index]); - if($task->isSync()){ - unset($this->runners[$this->taskId]); - } - return true; - } - } - return false; - } - -} \ No newline at end of file diff --git a/src/PocketMine/scheduler/Task.php b/src/PocketMine/scheduler/Task.php new file mode 100644 index 000000000..f338b21e1 --- /dev/null +++ b/src/PocketMine/scheduler/Task.php @@ -0,0 +1,73 @@ +taskHandler; + } + + /** + * @return int + */ + public final function getTaskId(){ + if($this->taskHandler !== null){ + return $this->taskHandler->getTaskId(); + } + return -1; + } + + /** + * @param TaskHandler $taskHandler + */ + public final function setHandler(TaskHandler $taskHandler){ + if($this->taskHandler === null or $taskHandler === null){ + $this->taskHandler = $taskHandler; + } + } + + /** + * Actions to execute when run + * + * @param $currentTick + * + * @return void + */ + public abstract function onRun($currentTick); + + /** + * Actions to execute if the Task is cancelled + */ + public function onCancel(){ + + } + +} diff --git a/src/PocketMine/scheduler/TaskHandler.php b/src/PocketMine/scheduler/TaskHandler.php new file mode 100644 index 000000000..827263444 --- /dev/null +++ b/src/PocketMine/scheduler/TaskHandler.php @@ -0,0 +1,148 @@ +task = $task; + $this->taskId = $taskId; + $this->delay = $delay; + $this->period = $period; + } + + /** + * @return bool + */ + public function isCancelled(){ + return $this->cancelled === true; + } + + /** + * @return int + */ + public function getNextRun(){ + return $this->nextRun; + } + + /** + * @param int $ticks + */ + public function setNextRun($ticks){ + $this->nextRun = $ticks; + } + + /** + * @return int + */ + public function getTaskId(){ + return $this->taskId; + } + + /** + * @return Task + */ + public function getTask(){ + return $this->task; + } + + /** + * @return int + */ + public function getDelay(){ + return $this->delay; + } + + /** + * @return bool + */ + public function isDelayed(){ + return $this->delay > 0; + } + + /** + * @return bool + */ + public function isRepeating(){ + return $this->period > 0; + } + + /** + * @return int + */ + public function getPeriod(){ + return $this->period; + } + + public function cancel(){ + $this->task->onCancel(); + $this->remove(); + } + + public function remove(){ + $this->cancelled = true; + $this->task->setHandler(null); + } + + /** + * @param int $currentTick + */ + public function run($currentTick){ + $this->task->onRun($currentTick); + } +} \ No newline at end of file diff --git a/src/PocketMine/scheduler/TaskPool.php b/src/PocketMine/scheduler/TaskPool.php deleted file mode 100644 index ff1a77bd1..000000000 --- a/src/PocketMine/scheduler/TaskPool.php +++ /dev/null @@ -1,35 +0,0 @@ -workers = array(); - parent::__construct((int) $workers, "PocketMine\\Scheduler\\TaskWorker"); - } - - public function shutdown(){ - foreach($this->workers as $worker){ - $worker->shutdown(); - } - } -} \ No newline at end of file diff --git a/src/PocketMine/scheduler/TaskWorker.php b/src/PocketMine/scheduler/TaskWorker.php deleted file mode 100644 index ec4ef9105..000000000 --- a/src/PocketMine/scheduler/TaskWorker.php +++ /dev/null @@ -1,31 +0,0 @@ -