mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-04-22 16:51:42 +00:00
cannot call async event in sync context + remove Event dependency for AsyncEventDelegate
This commit is contained in:
parent
dc85bba995
commit
ed739cff4f
@ -25,13 +25,17 @@ namespace pocketmine\event;
|
||||
|
||||
use pocketmine\promise\Promise;
|
||||
use pocketmine\promise\PromiseResolver;
|
||||
use pocketmine\timings\Timings;
|
||||
use pocketmine\utils\ObjectSet;
|
||||
use function array_shift;
|
||||
use function count;
|
||||
|
||||
final class AsyncEventDelegate extends Event{
|
||||
final class AsyncEventDelegate{
|
||||
/** @phpstan-var ObjectSet<Promise<null>> $promises */
|
||||
private ObjectSet $promises;
|
||||
/** @var array<class-string<AsyncEvent&Event>, int> $delegatesCall */
|
||||
private static array $delegatesCallDepth = [];
|
||||
private const MAX_EVENT_CALL_DEPTH = 50;
|
||||
|
||||
public function __construct(
|
||||
private AsyncEvent&Event $event
|
||||
@ -42,9 +46,27 @@ final class AsyncEventDelegate extends Event{
|
||||
/**
|
||||
* @phpstan-return Promise<null>
|
||||
*/
|
||||
public function callAsync() : Promise{
|
||||
public function call() : Promise{
|
||||
$this->promises->clear();
|
||||
return $this->callDepth($this->callAsyncDepth(...));
|
||||
if(!isset(self::$delegatesCallDepth[$class = $this->event::class])){
|
||||
self::$delegatesCallDepth[$class] = 0;
|
||||
}
|
||||
|
||||
if(self::$delegatesCallDepth[$class] >= self::MAX_EVENT_CALL_DEPTH){
|
||||
//this exception will be caught by the parent event call if all else fails
|
||||
throw new \RuntimeException("Recursive event call detected (reached max depth of " . self::MAX_EVENT_CALL_DEPTH . " calls)");
|
||||
}
|
||||
|
||||
$timings = Timings::getAsyncEventTimings($this->event);
|
||||
$timings->startTiming();
|
||||
|
||||
++self::$delegatesCallDepth[$class];
|
||||
try{
|
||||
return $this->callAsyncDepth();
|
||||
}finally{
|
||||
--self::$delegatesCallDepth[$class];
|
||||
$timings->stopTiming();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -32,9 +32,6 @@ trait AsyncEventTrait {
|
||||
* @phpstan-return Promise<null>
|
||||
*/
|
||||
final public function callAsync() : Promise{
|
||||
if(!isset($this->delegate)){
|
||||
$this->delegate = new AsyncEventDelegate($this);
|
||||
}
|
||||
return $this->delegate->callAsync();
|
||||
return (new AsyncEventDelegate($this))->call();
|
||||
}
|
||||
}
|
||||
|
@ -47,32 +47,24 @@ abstract class Event{
|
||||
* @throws \RuntimeException if event call recursion reaches the max depth limit
|
||||
*/
|
||||
public function call() : void{
|
||||
$this->callDepth(function(){
|
||||
$handlers = HandlerListManager::global()->getHandlersFor(static::class);
|
||||
|
||||
foreach($handlers as $registration){
|
||||
$registration->callEvent($this);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @template T
|
||||
* @phpstan-param \Closure() : T $closure
|
||||
* @phpstan-return T
|
||||
*/
|
||||
final protected function callDepth(\Closure $closure) : mixed{
|
||||
if(self::$eventCallDepth >= self::MAX_EVENT_CALL_DEPTH){
|
||||
//this exception will be caught by the parent event call if all else fails
|
||||
throw new \RuntimeException("Recursive event call detected (reached max depth of " . self::MAX_EVENT_CALL_DEPTH . " calls)");
|
||||
}
|
||||
if($this instanceof AsyncEvent){
|
||||
throw new \InvalidArgumentException("Cannot call async event synchronously");
|
||||
}
|
||||
|
||||
$timings = Timings::getEventTimings($this);
|
||||
$timings->startTiming();
|
||||
|
||||
$handlers = HandlerListManager::global()->getHandlersFor(static::class);
|
||||
|
||||
++self::$eventCallDepth;
|
||||
try{
|
||||
return $closure();
|
||||
foreach($handlers as $registration){
|
||||
$registration->callEvent($this);
|
||||
}
|
||||
}finally{
|
||||
--self::$eventCallDepth;
|
||||
$timings->stopTiming();
|
||||
|
@ -25,6 +25,7 @@ namespace pocketmine\timings;
|
||||
|
||||
use pocketmine\block\tile\Tile;
|
||||
use pocketmine\entity\Entity;
|
||||
use pocketmine\event\AsyncEvent;
|
||||
use pocketmine\event\Event;
|
||||
use pocketmine\network\mcpe\protocol\ClientboundPacket;
|
||||
use pocketmine\network\mcpe\protocol\ServerboundPacket;
|
||||
@ -113,6 +114,8 @@ abstract class Timings{
|
||||
|
||||
/** @var TimingsHandler[] */
|
||||
private static array $events = [];
|
||||
/** @var TimingsHandler[] */
|
||||
private static array $asyncEvents = [];
|
||||
/** @var TimingsHandler[][] */
|
||||
private static array $eventHandlers = [];
|
||||
|
||||
@ -304,6 +307,15 @@ abstract class Timings{
|
||||
return self::$events[$eventClass];
|
||||
}
|
||||
|
||||
public static function getAsyncEventTimings(AsyncEvent&Event $event) : TimingsHandler{
|
||||
$eventClass = get_class($event);
|
||||
if(!isset(self::$asyncEvents[$eventClass])){
|
||||
self::$asyncEvents[$eventClass] = new TimingsHandler(self::shortenCoreClassName($eventClass, "pocketmine\\event\\"), group: "Events");
|
||||
}
|
||||
|
||||
return self::$asyncEvents[$eventClass];
|
||||
}
|
||||
|
||||
/**
|
||||
* @phpstan-template TEvent of Event
|
||||
* @phpstan-param class-string<TEvent> $event
|
||||
|
Loading…
x
Reference in New Issue
Block a user